image-view.c revision 46ff2676b1044ea4101ac7a59b83289cd8f6cfda
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%                                John Cristy                                  %
22%                                March 2003                                   %
23%                                                                             %
24%                                                                             %
25%  Copyright 1999-2013 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*/
57struct _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*/
103MagickExport ImageView *CloneImageView(const ImageView *image_view)
104{
105  ImageView
106    *clone_view;
107
108  assert(image_view != (ImageView *) NULL);
109  assert(image_view->signature == MagickSignature);
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=MagickSignature;
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*/
146MagickExport ImageView *DestroyImageView(ImageView *image_view)
147{
148  assert(image_view != (ImageView *) NULL);
149  assert(image_view->signature == MagickSignature);
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=(~MagickSignature);
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*/
210MagickExport 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    width;
228#endif
229
230  ssize_t
231    y;
232
233  assert(source != (ImageView *) NULL);
234  assert(source->signature == MagickSignature);
235  if (transfer == (DuplexTransferImageViewMethod) NULL)
236    return(MagickFalse);
237  source_image=source->image;
238  destination_image=destination->image;
239  status=SetImageStorageClass(destination_image,DirectClass,
240    destination->exception);
241  if (status == MagickFalse)
242    return(MagickFalse);
243  status=MagickTrue;
244  progress=0;
245#if defined(MAGICKCORE_OPENMP_SUPPORT)
246  height=source->extent.height-source->extent.y;
247  width=source->extent.width-source->extent.x;
248  #pragma omp parallel for schedule(static,4) shared(progress,status) \
249    dynamic_number_threads(source_image,width,height,1)
250#endif
251  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
252  {
253    const int
254      id = GetOpenMPThreadId();
255
256    MagickBooleanType
257      sync;
258
259    register const Quantum
260      *restrict duplex_pixels,
261      *restrict pixels;
262
263    register Quantum
264      *restrict destination_pixels;
265
266    if (status == MagickFalse)
267      continue;
268    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
269      source->extent.width,1,source->exception);
270    if (pixels == (const Quantum *) NULL)
271      {
272        status=MagickFalse;
273        continue;
274      }
275    duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
276      duplex->extent.width,1,duplex->exception);
277    if (duplex_pixels == (const Quantum *) NULL)
278      {
279        status=MagickFalse;
280        continue;
281      }
282    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
283      destination->extent.x,y,destination->extent.width,1,
284      destination->exception);
285    if (destination_pixels == (Quantum *) NULL)
286      {
287        status=MagickFalse;
288        continue;
289      }
290    if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
291      status=MagickFalse;
292    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
293    if (sync == MagickFalse)
294      status=MagickFalse;
295    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
296      {
297        MagickBooleanType
298          proceed;
299
300#if defined(MAGICKCORE_OPENMP_SUPPORT)
301        #pragma omp critical (MagickCore_DuplexTransferImageViewIterator)
302#endif
303        proceed=SetImageProgress(source_image,source->description,progress++,
304          source->extent.height);
305        if (proceed == MagickFalse)
306          status=MagickFalse;
307      }
308  }
309  return(status);
310}
311
312/*
313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314%                                                                             %
315%                                                                             %
316%                                                                             %
317%   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           %
318%                                                                             %
319%                                                                             %
320%                                                                             %
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322%
323%  GetImageViewAuthenticMetacontent() returns the image view authentic
324%  meta-content.
325%
326%  The format of the GetImageViewAuthenticPixels method is:
327%
328%      void *GetImageViewAuthenticMetacontent(
329%        const ImageView *image_view)
330%
331%  A description of each parameter follows:
332%
333%    o image_view: the image view.
334%
335*/
336MagickExport void *GetImageViewAuthenticMetacontent(
337  const ImageView *image_view)
338{
339  assert(image_view != (ImageView *) NULL);
340  assert(image_view->signature == MagickSignature);
341  return(GetCacheViewAuthenticMetacontent(image_view->view));
342}
343
344/*
345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346%                                                                             %
347%                                                                             %
348%                                                                             %
349%   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                     %
350%                                                                             %
351%                                                                             %
352%                                                                             %
353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354%
355%  GetImageViewAuthenticPixels() returns the image view authentic pixels.
356%
357%  The format of the GetImageViewAuthenticPixels method is:
358%
359%      Quantum *GetImageViewAuthenticPixels(const ImageView *image_view)
360%
361%  A description of each parameter follows:
362%
363%    o image_view: the image view.
364%
365*/
366MagickExport Quantum *GetImageViewAuthenticPixels(
367  const ImageView *image_view)
368{
369  assert(image_view != (ImageView *) NULL);
370  assert(image_view->signature == MagickSignature);
371  return(GetCacheViewAuthenticPixelQueue(image_view->view));
372}
373
374/*
375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376%                                                                             %
377%                                                                             %
378%                                                                             %
379%   G e t I m a g e V i e w E x c e p t i o n                                 %
380%                                                                             %
381%                                                                             %
382%                                                                             %
383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384%
385%  GetImageViewException() returns the severity, reason, and description of any
386%  error that occurs when utilizing a image view.
387%
388%  The format of the GetImageViewException method is:
389%
390%      char *GetImageViewException(const PixelImage *image_view,
391%        ExceptionType *severity)
392%
393%  A description of each parameter follows:
394%
395%    o image_view: the pixel image_view.
396%
397%    o severity: the severity of the error is returned here.
398%
399*/
400MagickExport char *GetImageViewException(const ImageView *image_view,
401  ExceptionType *severity)
402{
403  char
404    *description;
405
406  assert(image_view != (const ImageView *) NULL);
407  assert(image_view->signature == MagickSignature);
408  assert(severity != (ExceptionType *) NULL);
409  *severity=image_view->exception->severity;
410  description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
411    sizeof(*description));
412  if (description == (char *) NULL)
413    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
414  *description='\0';
415  if (image_view->exception->reason != (char *) NULL)
416    (void) CopyMagickString(description,GetLocaleExceptionMessage(
417      image_view->exception->severity,image_view->exception->reason),
418        MaxTextExtent);
419  if (image_view->exception->description != (char *) NULL)
420    {
421      (void) ConcatenateMagickString(description," (",MaxTextExtent);
422      (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
423        image_view->exception->severity,image_view->exception->description),
424        MaxTextExtent);
425      (void) ConcatenateMagickString(description,")",MaxTextExtent);
426    }
427  return(description);
428}
429
430/*
431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432%                                                                             %
433%                                                                             %
434%                                                                             %
435%   G e t I m a g e V i e w E x t e n t                                       %
436%                                                                             %
437%                                                                             %
438%                                                                             %
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440%
441%  GetImageViewExtent() returns the image view extent.
442%
443%  The format of the GetImageViewExtent method is:
444%
445%      RectangleInfo GetImageViewExtent(const ImageView *image_view)
446%
447%  A description of each parameter follows:
448%
449%    o image_view: the image view.
450%
451*/
452MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
453{
454  assert(image_view != (ImageView *) NULL);
455  assert(image_view->signature == MagickSignature);
456  return(image_view->extent);
457}
458
459/*
460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461%                                                                             %
462%                                                                             %
463%                                                                             %
464%   G e t I m a g e V i e w I m a g e                                         %
465%                                                                             %
466%                                                                             %
467%                                                                             %
468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469%
470%  GetImageViewImage() returns the image associated with the image view.
471%
472%  The format of the GetImageViewImage method is:
473%
474%      MagickCore *GetImageViewImage(const ImageView *image_view)
475%
476%  A description of each parameter follows:
477%
478%    o image_view: the image view.
479%
480*/
481MagickExport Image *GetImageViewImage(const ImageView *image_view)
482{
483  assert(image_view != (ImageView *) NULL);
484  assert(image_view->signature == MagickSignature);
485  return(image_view->image);
486}
487
488/*
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%                                                                             %
491%                                                                             %
492%                                                                             %
493%   G e t I m a g e V i e w I t e r a t o r                                   %
494%                                                                             %
495%                                                                             %
496%                                                                             %
497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498%
499%  GetImageViewIterator() iterates over the image view in parallel and calls
500%  your get method for each scanline of the view.  The pixel extent is
501%  not confined to the image canvas-- that is you can include negative offsets
502%  or widths or heights that exceed the image dimension.  Any updates to
503%  the pixels in your callback are ignored.
504%
505%  The callback signature is:
506%
507%      MagickBooleanType GetImageViewMethod(const ImageView *source,
508%        const ssize_t y,const int thread_id,void *context)
509%
510%  Use this pragma if the view is not single threaded:
511%
512%    #pragma omp critical
513%
514%  to define a section of code in your callback get method that must be
515%  executed by a single thread at a time.
516%
517%  The format of the GetImageViewIterator method is:
518%
519%      MagickBooleanType GetImageViewIterator(ImageView *source,
520%        GetImageViewMethod get,void *context)
521%
522%  A description of each parameter follows:
523%
524%    o source: the source image view.
525%
526%    o get: the get callback method.
527%
528%    o context: the user defined context.
529%
530*/
531MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
532  GetImageViewMethod get,void *context)
533{
534  Image
535    *source_image;
536
537  MagickBooleanType
538    status;
539
540  MagickOffsetType
541    progress;
542
543#if defined(MAGICKCORE_OPENMP_SUPPORT)
544  size_t
545    height,
546    width;
547#endif
548
549  ssize_t
550    y;
551
552  assert(source != (ImageView *) NULL);
553  assert(source->signature == MagickSignature);
554  if (get == (GetImageViewMethod) NULL)
555    return(MagickFalse);
556  source_image=source->image;
557  status=MagickTrue;
558  progress=0;
559#if defined(MAGICKCORE_OPENMP_SUPPORT)
560  height=source->extent.height-source->extent.y;
561  width=source->extent.width-source->extent.x;
562  #pragma omp parallel for schedule(static,4) shared(progress,status) \
563    dynamic_number_threads(source_image,width,height,1)
564#endif
565  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
566  {
567    const int
568      id = GetOpenMPThreadId();
569
570    register const Quantum
571      *pixels;
572
573    if (status == MagickFalse)
574      continue;
575    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
576      source->extent.width,1,source->exception);
577    if (pixels == (const Quantum *) NULL)
578      {
579        status=MagickFalse;
580        continue;
581      }
582    if (get(source,y,id,context) == MagickFalse)
583      status=MagickFalse;
584    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
585      {
586        MagickBooleanType
587          proceed;
588
589#if defined(MAGICKCORE_OPENMP_SUPPORT)
590        #pragma omp critical (MagickCore_GetImageViewIterator)
591#endif
592        proceed=SetImageProgress(source_image,source->description,progress++,
593          source->extent.height);
594        if (proceed == MagickFalse)
595          status=MagickFalse;
596      }
597  }
598  return(status);
599}
600
601/*
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603%                                                                             %
604%                                                                             %
605%                                                                             %
606%   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     %
607%                                                                             %
608%                                                                             %
609%                                                                             %
610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611%
612%  GetImageViewVirtualMetacontent() returns the image view virtual
613%  meta-content.
614%
615%  The format of the GetImageViewVirtualMetacontent method is:
616%
617%      const void *GetImageViewVirtualMetacontent(
618%        const ImageView *image_view)
619%
620%  A description of each parameter follows:
621%
622%    o image_view: the image view.
623%
624*/
625MagickExport const void *GetImageViewVirtualMetacontent(
626  const ImageView *image_view)
627{
628  assert(image_view != (ImageView *) NULL);
629  assert(image_view->signature == MagickSignature);
630  return(GetCacheViewVirtualMetacontent(image_view->view));
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635%                                                                             %
636%                                                                             %
637%                                                                             %
638%   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                         %
639%                                                                             %
640%                                                                             %
641%                                                                             %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
644%  GetImageViewVirtualPixels() returns the image view virtual pixels.
645%
646%  The format of the GetImageViewVirtualPixels method is:
647%
648%      const Quantum *GetImageViewVirtualPixels(const ImageView *image_view)
649%
650%  A description of each parameter follows:
651%
652%    o image_view: the image view.
653%
654*/
655MagickExport const Quantum *GetImageViewVirtualPixels(
656  const ImageView *image_view)
657{
658  assert(image_view != (ImageView *) NULL);
659  assert(image_view->signature == MagickSignature);
660  return(GetCacheViewVirtualPixelQueue(image_view->view));
661}
662
663/*
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%                                                                             %
666%                                                                             %
667%                                                                             %
668%   I s I m a g e V i e w                                                     %
669%                                                                             %
670%                                                                             %
671%                                                                             %
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673%
674%  IsImageView() returns MagickTrue if the the parameter is verified as a image
675%  view object.
676%
677%  The format of the IsImageView method is:
678%
679%      MagickBooleanType IsImageView(const ImageView *image_view)
680%
681%  A description of each parameter follows:
682%
683%    o image_view: the image view.
684%
685*/
686MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
687{
688  if (image_view == (const ImageView *) NULL)
689    return(MagickFalse);
690  if (image_view->signature != MagickSignature)
691    return(MagickFalse);
692  return(MagickTrue);
693}
694
695/*
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697%                                                                             %
698%                                                                             %
699%                                                                             %
700%   N e w I m a g e V i e w                                                   %
701%                                                                             %
702%                                                                             %
703%                                                                             %
704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
705%
706%  NewImageView() returns a image view required for all other methods in the
707%  Image View API.
708%
709%  The format of the NewImageView method is:
710%
711%      ImageView *NewImageView(MagickCore *wand,ExceptionInfo *exception)
712%
713%  A description of each parameter follows:
714%
715%    o image: the image.
716%
717%    o exception: return any errors or warnings in this structure.
718%
719*/
720MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception)
721{
722  ImageView
723    *image_view;
724
725  assert(image != (Image *) NULL);
726  assert(image->signature == MagickSignature);
727  image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
728  if (image_view == (ImageView *) NULL)
729    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
730  (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
731  image_view->description=ConstantString("ImageView");
732  image_view->image=image;
733  image_view->view=AcquireVirtualCacheView(image_view->image,exception);
734  image_view->extent.width=image->columns;
735  image_view->extent.height=image->rows;
736  image_view->extent.x=0;
737  image_view->extent.y=0;
738  image_view->exception=AcquireExceptionInfo();
739  image_view->debug=IsEventLogging();
740  image_view->signature=MagickSignature;
741  return(image_view);
742}
743
744/*
745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746%                                                                             %
747%                                                                             %
748%                                                                             %
749%   N e w I m a g e V i e w R e g i o n                                       %
750%                                                                             %
751%                                                                             %
752%                                                                             %
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754%
755%  NewImageViewRegion() returns a image view required for all other methods
756%  in the Image View API.
757%
758%  The format of the NewImageViewRegion method is:
759%
760%      ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
761%        const ssize_t y,const size_t width,const size_t height,
762%        ExceptionInfo *exception)
763%
764%  A description of each parameter follows:
765%
766%    o wand: the magick wand.
767%
768%    o x,y,columns,rows:  These values define the perimeter of a extent of
769%      pixel_wands view.
770%
771%    o exception: return any errors or warnings in this structure.
772%
773*/
774MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
775  const ssize_t y,const size_t width,const size_t height,
776  ExceptionInfo *exception)
777{
778  ImageView
779    *image_view;
780
781  assert(image != (Image *) NULL);
782  assert(image->signature == MagickSignature);
783  image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
784  if (image_view == (ImageView *) NULL)
785    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
786  (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
787  image_view->description=ConstantString("ImageView");
788  image_view->view=AcquireVirtualCacheView(image_view->image,exception);
789  image_view->image=image;
790  image_view->extent.width=width;
791  image_view->extent.height=height;
792  image_view->extent.x=x;
793  image_view->extent.y=y;
794  image_view->exception=AcquireExceptionInfo();
795  image_view->debug=IsEventLogging();
796  image_view->signature=MagickSignature;
797  return(image_view);
798}
799
800/*
801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802%                                                                             %
803%                                                                             %
804%                                                                             %
805%   S e t I m a g e V i e w D e s c r i p t i o n                             %
806%                                                                             %
807%                                                                             %
808%                                                                             %
809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
810%
811%  SetImageViewDescription() associates a description with an image view.
812%
813%  The format of the SetImageViewDescription method is:
814%
815%      void SetImageViewDescription(ImageView *image_view,
816%        const char *description)
817%
818%  A description of each parameter follows:
819%
820%    o image_view: the image view.
821%
822%    o description: the image view description.
823%
824*/
825MagickExport void SetImageViewDescription(ImageView *image_view,
826  const char *description)
827{
828  assert(image_view != (ImageView *) NULL);
829  assert(image_view->signature == MagickSignature);
830  image_view->description=ConstantString(description);
831}
832
833/*
834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835%                                                                             %
836%                                                                             %
837%                                                                             %
838%   S e t I m a g e V i e w I t e r a t o r                                   %
839%                                                                             %
840%                                                                             %
841%                                                                             %
842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843%
844%  SetImageViewIterator() iterates over the image view in parallel and calls
845%  your set method for each scanline of the view.  The pixel extent is
846%  confined to the image canvas-- that is no negative offsets or widths or
847%  heights that exceed the image dimension.  The pixels are initiallly
848%  undefined and any settings you make in the callback method are automagically
849%  synced back to your image.
850%
851%  The callback signature is:
852%
853%      MagickBooleanType SetImageViewMethod(ImageView *destination,
854%        const ssize_t y,const int thread_id,void *context)
855%
856%  Use this pragma if the view is not single threaded:
857%
858%    #pragma omp critical
859%
860%  to define a section of code in your callback set method that must be
861%  executed by a single thread at a time.
862%
863%  The format of the SetImageViewIterator method is:
864%
865%      MagickBooleanType SetImageViewIterator(ImageView *destination,
866%        SetImageViewMethod set,void *context)
867%
868%  A description of each parameter follows:
869%
870%    o destination: the image view.
871%
872%    o set: the set callback method.
873%
874%    o context: the user defined context.
875%
876*/
877MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
878  SetImageViewMethod set,void *context)
879{
880  Image
881    *destination_image;
882
883  MagickBooleanType
884    status;
885
886  MagickOffsetType
887    progress;
888
889#if defined(MAGICKCORE_OPENMP_SUPPORT)
890  size_t
891    height,
892    width;
893#endif
894
895  ssize_t
896    y;
897
898  assert(destination != (ImageView *) NULL);
899  assert(destination->signature == MagickSignature);
900  if (set == (SetImageViewMethod) NULL)
901    return(MagickFalse);
902  destination_image=destination->image;
903  status=SetImageStorageClass(destination_image,DirectClass,
904    destination->exception);
905  if (status == MagickFalse)
906    return(MagickFalse);
907  status=MagickTrue;
908  progress=0;
909#if defined(MAGICKCORE_OPENMP_SUPPORT)
910  height=destination->extent.height-destination->extent.y;
911  width=destination->extent.width-destination->extent.x;
912  #pragma omp parallel for schedule(static,4) shared(progress,status) \
913    dynamic_number_threads(destination_image,width,height,1)
914#endif
915  for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
916  {
917    const int
918      id = GetOpenMPThreadId();
919
920    MagickBooleanType
921      sync;
922
923    register Quantum
924      *restrict pixels;
925
926    if (status == MagickFalse)
927      continue;
928    pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
929      y,destination->extent.width,1,destination->exception);
930    if (pixels == (Quantum *) NULL)
931      {
932        status=MagickFalse;
933        continue;
934      }
935    if (set(destination,y,id,context) == MagickFalse)
936      status=MagickFalse;
937    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
938    if (sync == MagickFalse)
939      status=MagickFalse;
940    if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
941      {
942        MagickBooleanType
943          proceed;
944
945#if defined(MAGICKCORE_OPENMP_SUPPORT)
946        #pragma omp critical (MagickCore_SetImageViewIterator)
947#endif
948        proceed=SetImageProgress(destination_image,destination->description,
949          progress++,destination->extent.height);
950        if (proceed == MagickFalse)
951          status=MagickFalse;
952      }
953  }
954  return(status);
955}
956
957/*
958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959%                                                                             %
960%                                                                             %
961%                                                                             %
962%   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                         %
963%                                                                             %
964%                                                                             %
965%                                                                             %
966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
967%
968%  TransferImageViewIterator() iterates over two image views in parallel and
969%  calls your transfer method for each scanline of the view.  The source pixel
970%  extent is not confined to the image canvas-- that is you can include
971%  negative offsets or widths or heights that exceed the image dimension.
972%  However, the destination image view is confined to the image canvas-- that
973%  is no negative offsets or widths or heights that exceed the image dimension
974%  are permitted.
975%
976%  The callback signature is:
977%
978%      MagickBooleanType TransferImageViewMethod(const ImageView *source,
979%        ImageView *destination,const ssize_t y,const int thread_id,
980%        void *context)
981%
982%  Use this pragma if the view is not single threaded:
983%
984%    #pragma omp critical
985%
986%  to define a section of code in your callback transfer method that must be
987%  executed by a single thread at a time.
988%
989%  The format of the TransferImageViewIterator method is:
990%
991%      MagickBooleanType TransferImageViewIterator(ImageView *source,
992%        ImageView *destination,TransferImageViewMethod transfer,void *context)
993%
994%  A description of each parameter follows:
995%
996%    o source: the source image view.
997%
998%    o destination: the destination image view.
999%
1000%    o transfer: the transfer callback method.
1001%
1002%    o context: the user defined context.
1003%
1004*/
1005MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1006  ImageView *destination,TransferImageViewMethod transfer,void *context)
1007{
1008  Image
1009    *destination_image,
1010    *source_image;
1011
1012  MagickBooleanType
1013    status;
1014
1015  MagickOffsetType
1016    progress;
1017
1018#if defined(MAGICKCORE_OPENMP_SUPPORT)
1019  size_t
1020    height,
1021    width;
1022#endif
1023
1024  ssize_t
1025    y;
1026
1027  assert(source != (ImageView *) NULL);
1028  assert(source->signature == MagickSignature);
1029  if (transfer == (TransferImageViewMethod) NULL)
1030    return(MagickFalse);
1031  source_image=source->image;
1032  destination_image=destination->image;
1033  status=SetImageStorageClass(destination_image,DirectClass,
1034    destination->exception);
1035  if (status == MagickFalse)
1036    return(MagickFalse);
1037  status=MagickTrue;
1038  progress=0;
1039#if defined(MAGICKCORE_OPENMP_SUPPORT)
1040  height=source->extent.height-source->extent.y;
1041  width=source->extent.width-source->extent.x;
1042  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1043    dynamic_number_threads(source_image,width,height,1)
1044#endif
1045  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1046  {
1047    const int
1048      id = GetOpenMPThreadId();
1049
1050    MagickBooleanType
1051      sync;
1052
1053    register const Quantum
1054      *restrict pixels;
1055
1056    register Quantum
1057      *restrict destination_pixels;
1058
1059    if (status == MagickFalse)
1060      continue;
1061    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1062      source->extent.width,1,source->exception);
1063    if (pixels == (const Quantum *) NULL)
1064      {
1065        status=MagickFalse;
1066        continue;
1067      }
1068    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1069      destination->extent.x,y,destination->extent.width,1,
1070      destination->exception);
1071    if (destination_pixels == (Quantum *) NULL)
1072      {
1073        status=MagickFalse;
1074        continue;
1075      }
1076    if (transfer(source,destination,y,id,context) == MagickFalse)
1077      status=MagickFalse;
1078    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1079    if (sync == MagickFalse)
1080      status=MagickFalse;
1081    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1082      {
1083        MagickBooleanType
1084          proceed;
1085
1086#if defined(MAGICKCORE_OPENMP_SUPPORT)
1087        #pragma omp critical (MagickCore_TransferImageViewIterator)
1088#endif
1089        proceed=SetImageProgress(source_image,source->description,progress++,
1090          source->extent.height);
1091        if (proceed == MagickFalse)
1092          status=MagickFalse;
1093      }
1094  }
1095  return(status);
1096}
1097
1098/*
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100%                                                                             %
1101%                                                                             %
1102%                                                                             %
1103%   U p d a t e I m a g e V i e w I t e r a t o r                             %
1104%                                                                             %
1105%                                                                             %
1106%                                                                             %
1107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108%
1109%  UpdateImageViewIterator() iterates over the image view in parallel and calls
1110%  your update method for each scanline of the view.  The pixel extent is
1111%  confined to the image canvas-- that is no negative offsets or widths or
1112%  heights that exceed the image dimension are permitted.  Updates to pixels
1113%  in your callback are automagically synced back to the image.
1114%
1115%  The callback signature is:
1116%
1117%      MagickBooleanType UpdateImageViewMethod(ImageView *source,
1118%        const ssize_t y,const int thread_id,void *context)
1119%
1120%  Use this pragma if the view is not single threaded:
1121%
1122%    #pragma omp critical
1123%
1124%  to define a section of code in your callback update method that must be
1125%  executed by a single thread at a time.
1126%
1127%  The format of the UpdateImageViewIterator method is:
1128%
1129%      MagickBooleanType UpdateImageViewIterator(ImageView *source,
1130%        UpdateImageViewMethod update,void *context)
1131%
1132%  A description of each parameter follows:
1133%
1134%    o source: the source image view.
1135%
1136%    o update: the update callback method.
1137%
1138%    o context: the user defined context.
1139%
1140*/
1141MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1142  UpdateImageViewMethod update,void *context)
1143{
1144  Image
1145    *source_image;
1146
1147  MagickBooleanType
1148    status;
1149
1150  MagickOffsetType
1151    progress;
1152
1153#if defined(MAGICKCORE_OPENMP_SUPPORT)
1154  size_t
1155    height,
1156    width;
1157#endif
1158
1159  ssize_t
1160    y;
1161
1162  assert(source != (ImageView *) NULL);
1163  assert(source->signature == MagickSignature);
1164  if (update == (UpdateImageViewMethod) NULL)
1165    return(MagickFalse);
1166  source_image=source->image;
1167  status=SetImageStorageClass(source_image,DirectClass,source->exception);
1168  if (status == MagickFalse)
1169    return(MagickFalse);
1170  status=MagickTrue;
1171  progress=0;
1172#if defined(MAGICKCORE_OPENMP_SUPPORT)
1173  height=source->extent.height-source->extent.y;
1174  width=source->extent.width-source->extent.x;
1175  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1176    dynamic_number_threads(source_image,width,height,1)
1177#endif
1178  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1179  {
1180    const int
1181      id = GetOpenMPThreadId();
1182
1183    register Quantum
1184      *restrict pixels;
1185
1186    if (status == MagickFalse)
1187      continue;
1188    pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1189      source->extent.width,1,source->exception);
1190    if (pixels == (Quantum *) NULL)
1191      {
1192        status=MagickFalse;
1193        continue;
1194      }
1195    if (update(source,y,id,context) == MagickFalse)
1196      status=MagickFalse;
1197    status=SyncCacheViewAuthenticPixels(source->view,source->exception);
1198    if (status == MagickFalse)
1199      status=MagickFalse;
1200    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1201      {
1202        MagickBooleanType
1203          proceed;
1204
1205#if defined(MAGICKCORE_OPENMP_SUPPORT)
1206        #pragma omp critical (MagickCore_UpdateImageViewIterator)
1207#endif
1208        proceed=SetImageProgress(source_image,source->description,progress++,
1209          source->extent.height);
1210        if (proceed == MagickFalse)
1211          status=MagickFalse;
1212      }
1213  }
1214  return(status);
1215}
1216