blob: 136830ec6f4bd5ce5cf8d32d7f48dae64781f87f [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
cristy7eb1b7a2010-06-26 15:47:49 +00005% 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 %
cristy3ed852e2009-09-05 21:47:34 +000010% %
cristycc34c492010-06-26 23:49:12 +000011% 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 %
cristy3ed852e2009-09-05 21:47:34 +000016% %
17% %
cristy7eb1b7a2010-06-26 15:47:49 +000018% MagickCore Image View Methods %
cristy3ed852e2009-09-05 21:47:34 +000019% %
20% Software Design %
21% John Cristy %
22% March 2003 %
23% %
24% %
cristy16af1cb2009-12-11 21:38:29 +000025% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000026% 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*/
cristy7eb1b7a2010-06-26 15:47:49 +000048#include "magick/studio.h"
49#include "magick/MagickCore.h"
50#include "magick/exception-private.h"
cristy3ed852e2009-09-05 21:47:34 +000051#include "magick/monitor-private.h"
52#include "magick/thread-private.h"
cristy3ed852e2009-09-05 21:47:34 +000053
54/*
55 Typedef declarations.
56*/
cristy7eb1b7a2010-06-26 15:47:49 +000057struct _ImageView
cristy3ed852e2009-09-05 21:47:34 +000058{
cristy3ed852e2009-09-05 21:47:34 +000059 ExceptionInfo
60 *exception;
61
cristy7eb1b7a2010-06-26 15:47:49 +000062 Image
63 *image;
cristy3ed852e2009-09-05 21:47:34 +000064
65 CacheView
66 *view;
67
68 RectangleInfo
69 region;
70
cristybb503372010-05-27 20:51:26 +000071 size_t
cristy3ed852e2009-09-05 21:47:34 +000072 number_threads;
73
cristy3ed852e2009-09-05 21:47:34 +000074 MagickBooleanType
75 debug;
76
cristybb503372010-05-27 20:51:26 +000077 size_t
cristy3ed852e2009-09-05 21:47:34 +000078 signature;
79};
80
81/*
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83% %
84% %
85% %
cristy7eb1b7a2010-06-26 15:47:49 +000086% C l o n e I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +000087% %
88% %
89% %
90%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91%
cristy73b7d4c2010-06-27 00:31:00 +000092% CloneImageView() makes a copy of the specified image view.
cristy3ed852e2009-09-05 21:47:34 +000093%
cristy7eb1b7a2010-06-26 15:47:49 +000094% The format of the CloneImageView method is:
cristy3ed852e2009-09-05 21:47:34 +000095%
cristy73b7d4c2010-06-27 00:31:00 +000096% ImageView *CloneImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +000097%
98% A description of each parameter follows:
99%
cristy73b7d4c2010-06-27 00:31:00 +0000100% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000101%
102*/
cristy73b7d4c2010-06-27 00:31:00 +0000103MagickExport ImageView *CloneImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000104{
cristy7eb1b7a2010-06-26 15:47:49 +0000105 ImageView
cristy3ed852e2009-09-05 21:47:34 +0000106 *clone_view;
107
cristy73b7d4c2010-06-27 00:31:00 +0000108 assert(image_view != (ImageView *) NULL);
109 assert(image_view->signature == MagickSignature);
cristy7eb1b7a2010-06-26 15:47:49 +0000110 clone_view=(ImageView *) AcquireAlignedMemory(1,sizeof(*clone_view));
111 if (clone_view == (ImageView *) NULL)
112 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000113 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
cristy3ed852e2009-09-05 21:47:34 +0000114 clone_view->exception=AcquireExceptionInfo();
cristy73b7d4c2010-06-27 00:31:00 +0000115 InheritException(clone_view->exception,image_view->exception);
116 clone_view->view=CloneCacheView(image_view->view);
117 clone_view->region=image_view->region;
118 clone_view->number_threads=image_view->number_threads;
119 clone_view->debug=image_view->debug;
cristy7eb1b7a2010-06-26 15:47:49 +0000120 clone_view->signature=MagickSignature;
cristy3ed852e2009-09-05 21:47:34 +0000121 return(clone_view);
122}
123
124/*
125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126% %
127% %
128% %
cristy7eb1b7a2010-06-26 15:47:49 +0000129% D e s t r o y I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000130% %
131% %
132% %
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134%
cristy73b7d4c2010-06-27 00:31:00 +0000135% DestroyImageView() deallocates memory associated with a image view.
cristy3ed852e2009-09-05 21:47:34 +0000136%
cristy7eb1b7a2010-06-26 15:47:49 +0000137% The format of the DestroyImageView method is:
cristy3ed852e2009-09-05 21:47:34 +0000138%
cristy73b7d4c2010-06-27 00:31:00 +0000139% ImageView *DestroyImageView(ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000140%
141% A description of each parameter follows:
142%
cristy73b7d4c2010-06-27 00:31:00 +0000143% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000144%
145*/
cristy73b7d4c2010-06-27 00:31:00 +0000146MagickExport ImageView *DestroyImageView(ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000147{
cristy73b7d4c2010-06-27 00:31:00 +0000148 assert(image_view != (ImageView *) NULL);
149 assert(image_view->signature == MagickSignature);
150 image_view->view=DestroyCacheView(image_view->view);
151 image_view->exception=DestroyExceptionInfo(image_view->exception);
152 image_view->signature=(~MagickSignature);
153 image_view=(ImageView *) RelinquishMagickMemory(image_view);
154 return(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000155}
156
157/*
158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159% %
160% %
161% %
cristy7eb1b7a2010-06-26 15:47:49 +0000162% 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 %
cristy3ed852e2009-09-05 21:47:34 +0000163% %
164% %
165% %
166%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167%
cristy73b7d4c2010-06-27 00:31:00 +0000168% DuplexTransferImageViewIterator() iterates over three image views in
cristy3ed852e2009-09-05 21:47:34 +0000169% parallel and calls your transfer method for each scanline of the view. The
170% source and duplex pixel region is not confined to the image canvas-- that is
171% you can include negative offsets or widths or heights that exceed the image
cristy73b7d4c2010-06-27 00:31:00 +0000172% dimension. However, the destination image view is confined to the image
cristy3ed852e2009-09-05 21:47:34 +0000173% canvas-- that is no negative offsets or widths or heights that exceed the
174% image dimension are permitted.
175%
cristy58739472010-06-26 20:27:18 +0000176% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000177%
178% #pragma omp critical
179%
180% to define a section of code in your callback transfer method that must be
181% executed by a single thread at a time.
182%
cristy7eb1b7a2010-06-26 15:47:49 +0000183% The format of the DuplexTransferImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000184%
cristy7eb1b7a2010-06-26 15:47:49 +0000185% MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
186% ImageView *duplex,ImageView *destination,
187% DuplexTransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000188%
189% A description of each parameter follows:
190%
cristy73b7d4c2010-06-27 00:31:00 +0000191% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +0000192%
cristy73b7d4c2010-06-27 00:31:00 +0000193% o duplex: the duplex image view.
cristy3ed852e2009-09-05 21:47:34 +0000194%
cristy73b7d4c2010-06-27 00:31:00 +0000195% o destination: the destination image view.
cristy3ed852e2009-09-05 21:47:34 +0000196%
197% o transfer: the transfer callback method.
198%
199% o context: the user defined context.
200%
201*/
cristy7eb1b7a2010-06-26 15:47:49 +0000202MagickExport MagickBooleanType DuplexTransferImageViewIterator(
203 ImageView *source,ImageView *duplex,ImageView *destination,
204 DuplexTransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000205{
cristy7eb1b7a2010-06-26 15:47:49 +0000206#define DuplexTransferImageViewTag "ImageView/DuplexTransfer"
cristy3ed852e2009-09-05 21:47:34 +0000207
208 ExceptionInfo
209 *exception;
210
211 Image
212 *destination_image,
213 *duplex_image,
214 *source_image;
215
cristy3ed852e2009-09-05 21:47:34 +0000216 MagickBooleanType
217 status;
218
cristycee97112010-05-28 00:44:52 +0000219 MagickOffsetType
220 progress;
221
222 ssize_t
223 y;
224
cristy7eb1b7a2010-06-26 15:47:49 +0000225 assert(source != (ImageView *) NULL);
226 assert(source->signature == MagickSignature);
227 if (transfer == (DuplexTransferImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000228 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000229 source_image=source->image;
230 duplex_image=duplex->image;
231 destination_image=destination->image;
cristy3ed852e2009-09-05 21:47:34 +0000232 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
233 return(MagickFalse);
234 status=MagickTrue;
235 progress=0;
236 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +0000237#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristycde47d32009-11-04 03:05:18 +0000238 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000239#endif
cristybb503372010-05-27 20:51:26 +0000240 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000241 {
242 MagickBooleanType
243 sync;
244
245 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000246 *restrict duplex_indexes,
247 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000248
249 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000250 *restrict duplex_pixels,
251 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000252
253 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000254 *restrict destination_indexes;
cristy3ed852e2009-09-05 21:47:34 +0000255
cristybb503372010-05-27 20:51:26 +0000256 register ssize_t
cristycc34c492010-06-26 23:49:12 +0000257 id;
cristy3ed852e2009-09-05 21:47:34 +0000258
259 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000260 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +0000261
262 if (status == MagickFalse)
263 continue;
264 id=GetOpenMPThreadId();
265 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
266 source->region.width,1,source->exception);
267 if (pixels == (const PixelPacket *) NULL)
268 {
269 status=MagickFalse;
270 continue;
271 }
272 indexes=GetCacheViewVirtualIndexQueue(source->view);
cristy3ed852e2009-09-05 21:47:34 +0000273 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->region.x,y,
274 duplex->region.width,1,duplex->exception);
275 if (duplex_pixels == (const PixelPacket *) NULL)
276 {
277 status=MagickFalse;
278 continue;
279 }
280 duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
cristy3ed852e2009-09-05 21:47:34 +0000281 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
282 destination->region.x,y,destination->region.width,1,exception);
283 if (destination_pixels == (PixelPacket *) NULL)
284 {
285 status=MagickFalse;
286 continue;
287 }
288 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
cristy3ed852e2009-09-05 21:47:34 +0000289 if (transfer(source,duplex,destination,context) == MagickFalse)
290 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000291 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
292 if (sync == MagickFalse)
293 {
294 InheritException(destination->exception,GetCacheViewException(
295 source->view));
296 status=MagickFalse;
297 }
298 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
299 {
300 MagickBooleanType
301 proceed;
302
cristyb5d5f722009-11-04 03:03:49 +0000303#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000304 #pragma omp critical (MagickCore_DuplexTransferImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000305#endif
cristy7eb1b7a2010-06-26 15:47:49 +0000306 proceed=SetImageProgress(source_image,DuplexTransferImageViewTag,
cristy3ed852e2009-09-05 21:47:34 +0000307 progress++,source->region.height);
308 if (proceed == MagickFalse)
309 status=MagickFalse;
310 }
311 }
312 return(status);
313}
314
315/*
316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317% %
318% %
319% %
cristycc34c492010-06-26 23:49:12 +0000320% G e t I m a g e V i e w A u t h e n t i c I n d e x e s %
321% %
322% %
323% %
324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325%
cristy73b7d4c2010-06-27 00:31:00 +0000326% GetImageViewAuthenticIndexes() returns the image view authentic indexes.
cristycc34c492010-06-26 23:49:12 +0000327%
328% The format of the GetImageViewAuthenticPixels method is:
329%
cristy73b7d4c2010-06-27 00:31:00 +0000330% IndexPacket *GetImageViewAuthenticIndexes(const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000331%
332% A description of each parameter follows:
333%
cristy73b7d4c2010-06-27 00:31:00 +0000334% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000335%
336*/
337MagickExport IndexPacket *GetImageViewAuthenticIndexes(
cristy73b7d4c2010-06-27 00:31:00 +0000338 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000339{
cristy73b7d4c2010-06-27 00:31:00 +0000340 assert(image_view != (ImageView *) NULL);
341 assert(image_view->signature == MagickSignature);
342 return(GetCacheViewAuthenticIndexQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000343}
344
345/*
346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347% %
348% %
349% %
350% 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 %
351% %
352% %
353% %
354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355%
cristy73b7d4c2010-06-27 00:31:00 +0000356% GetImageViewAuthenticPixels() returns the image view authentic pixels.
cristycc34c492010-06-26 23:49:12 +0000357%
358% The format of the GetImageViewAuthenticPixels method is:
359%
cristy73b7d4c2010-06-27 00:31:00 +0000360% PixelPacket *GetImageViewAuthenticPixels(const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000361%
362% A description of each parameter follows:
363%
cristy73b7d4c2010-06-27 00:31:00 +0000364% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000365%
366*/
367MagickExport PixelPacket *GetImageViewAuthenticPixels(
cristy73b7d4c2010-06-27 00:31:00 +0000368 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000369{
cristy73b7d4c2010-06-27 00:31:00 +0000370 assert(image_view != (ImageView *) NULL);
371 assert(image_view->signature == MagickSignature);
372 return(GetCacheViewAuthenticPixelQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000373}
374
375/*
376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377% %
378% %
379% %
cristy7eb1b7a2010-06-26 15:47:49 +0000380% G e t I m a g e V i e w E x c e p t i o n %
cristy3ed852e2009-09-05 21:47:34 +0000381% %
382% %
383% %
384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385%
cristy7eb1b7a2010-06-26 15:47:49 +0000386% GetImageViewException() returns the severity, reason, and description of any
cristy73b7d4c2010-06-27 00:31:00 +0000387% error that occurs when utilizing a image view.
cristy3ed852e2009-09-05 21:47:34 +0000388%
cristy7eb1b7a2010-06-26 15:47:49 +0000389% The format of the GetImageViewException method is:
cristy3ed852e2009-09-05 21:47:34 +0000390%
cristy73b7d4c2010-06-27 00:31:00 +0000391% char *GetImageViewException(const PixelImage *image_view,
cristy3ed852e2009-09-05 21:47:34 +0000392% ExceptionType *severity)
393%
394% A description of each parameter follows:
395%
cristy73b7d4c2010-06-27 00:31:00 +0000396% o image_view: the pixel image_view.
cristy3ed852e2009-09-05 21:47:34 +0000397%
398% o severity: the severity of the error is returned here.
399%
400*/
cristy73b7d4c2010-06-27 00:31:00 +0000401MagickExport char *GetImageViewException(const ImageView *image_view,
cristy3ed852e2009-09-05 21:47:34 +0000402 ExceptionType *severity)
403{
404 char
405 *description;
406
cristy73b7d4c2010-06-27 00:31:00 +0000407 assert(image_view != (const ImageView *) NULL);
408 assert(image_view->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +0000409 assert(severity != (ExceptionType *) NULL);
cristy73b7d4c2010-06-27 00:31:00 +0000410 *severity=image_view->exception->severity;
cristy3ed852e2009-09-05 21:47:34 +0000411 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
412 sizeof(*description));
413 if (description == (char *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000414 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000415 *description='\0';
cristy73b7d4c2010-06-27 00:31:00 +0000416 if (image_view->exception->reason != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000417 (void) CopyMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000418 image_view->exception->severity,image_view->exception->reason),
cristy3ed852e2009-09-05 21:47:34 +0000419 MaxTextExtent);
cristy73b7d4c2010-06-27 00:31:00 +0000420 if (image_view->exception->description != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000421 {
422 (void) ConcatenateMagickString(description," (",MaxTextExtent);
423 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000424 image_view->exception->severity,image_view->exception->description),
cristy3ed852e2009-09-05 21:47:34 +0000425 MaxTextExtent);
426 (void) ConcatenateMagickString(description,")",MaxTextExtent);
427 }
428 return(description);
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
cristy7eb1b7a2010-06-26 15:47:49 +0000436% G e t I m a g e V i e w H e i g h t %
cristy3ed852e2009-09-05 21:47:34 +0000437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
cristy73b7d4c2010-06-27 00:31:00 +0000442% GetImageViewHeight() returns the image view height.
cristy3ed852e2009-09-05 21:47:34 +0000443%
cristy7eb1b7a2010-06-26 15:47:49 +0000444% The format of the GetImageViewHeight method is:
cristy3ed852e2009-09-05 21:47:34 +0000445%
cristy73b7d4c2010-06-27 00:31:00 +0000446% size_t GetImageViewHeight(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000447%
448% A description of each parameter follows:
449%
cristy73b7d4c2010-06-27 00:31:00 +0000450% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000451%
452*/
cristy73b7d4c2010-06-27 00:31:00 +0000453MagickExport size_t GetImageViewHeight(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000454{
cristy73b7d4c2010-06-27 00:31:00 +0000455 assert(image_view != (ImageView *) NULL);
456 assert(image_view->signature == MagickSignature);
457 return(image_view->region.height);
458}
459
460/*
461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462% %
463% %
464% %
465% G e t I m a g e V i e w I m a g e %
466% %
467% %
468% %
469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470%
471% GetImageViewImage() returns the image associated with the image view.
472%
473% The format of the GetImageViewImage method is:
474%
475% MagickCore *GetImageViewImage(const ImageView *image_view)
476%
477% A description of each parameter follows:
478%
479% o image_view: the image view.
480%
481*/
482MagickExport Image *GetImageViewImage(const ImageView *image_view)
483{
484 assert(image_view != (ImageView *) NULL);
485 assert(image_view->signature == MagickSignature);
486 return(image_view->image);
cristy3ed852e2009-09-05 21:47:34 +0000487}
488
489/*
490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491% %
492% %
493% %
cristy7eb1b7a2010-06-26 15:47:49 +0000494% G e t I m a g e V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +0000495% %
496% %
497% %
498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499%
cristy73b7d4c2010-06-27 00:31:00 +0000500% GetImageViewIterator() iterates over the image view in parallel and calls
cristy3ed852e2009-09-05 21:47:34 +0000501% your get method for each scanline of the view. The pixel region is
502% not confined to the image canvas-- that is you can include negative offsets
503% or widths or heights that exceed the image dimension. Any updates to
504% the pixels in your callback are ignored.
505%
cristy58739472010-06-26 20:27:18 +0000506% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000507%
508% #pragma omp critical
509%
510% to define a section of code in your callback get method that must be
511% executed by a single thread at a time.
512%
cristy7eb1b7a2010-06-26 15:47:49 +0000513% The format of the GetImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000514%
cristy7eb1b7a2010-06-26 15:47:49 +0000515% MagickBooleanType GetImageViewIterator(ImageView *source,
516% GetImageViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000517%
518% A description of each parameter follows:
519%
cristy73b7d4c2010-06-27 00:31:00 +0000520% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +0000521%
522% o get: the get callback method.
523%
524% o context: the user defined context.
525%
526*/
cristy7eb1b7a2010-06-26 15:47:49 +0000527MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
528 GetImageViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000529{
cristy7eb1b7a2010-06-26 15:47:49 +0000530#define GetImageViewTag "ImageView/Get"
cristy3ed852e2009-09-05 21:47:34 +0000531
532 Image
533 *source_image;
534
cristy3ed852e2009-09-05 21:47:34 +0000535 MagickBooleanType
536 status;
537
cristycee97112010-05-28 00:44:52 +0000538 MagickOffsetType
539 progress;
540
541 ssize_t
542 y;
543
cristy7eb1b7a2010-06-26 15:47:49 +0000544 assert(source != (ImageView *) NULL);
545 assert(source->signature == MagickSignature);
546 if (get == (GetImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000547 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000548 source_image=source->image;
cristy3ed852e2009-09-05 21:47:34 +0000549 status=MagickTrue;
550 progress=0;
cristyb5d5f722009-11-04 03:03:49 +0000551#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy309f6132010-06-07 13:19:01 +0000552 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000553#endif
cristybb503372010-05-27 20:51:26 +0000554 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000555 {
556 register const IndexPacket
557 *indexes;
558
559 register const PixelPacket
560 *pixels;
561
cristybb503372010-05-27 20:51:26 +0000562 register ssize_t
cristycc34c492010-06-26 23:49:12 +0000563 id;
cristy3ed852e2009-09-05 21:47:34 +0000564
565 if (status == MagickFalse)
566 continue;
567 id=GetOpenMPThreadId();
568 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
569 source->region.width,1,source->exception);
570 if (pixels == (const PixelPacket *) NULL)
571 {
572 status=MagickFalse;
573 continue;
574 }
575 indexes=GetCacheViewVirtualIndexQueue(source->view);
cristy3ed852e2009-09-05 21:47:34 +0000576 if (get(source,context) == MagickFalse)
577 status=MagickFalse;
578 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
579 {
580 MagickBooleanType
581 proceed;
582
cristyb5d5f722009-11-04 03:03:49 +0000583#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000584 #pragma omp critical (MagickCore_GetImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000585#endif
cristy7eb1b7a2010-06-26 15:47:49 +0000586 proceed=SetImageProgress(source_image,GetImageViewTag,progress++,
cristy3ed852e2009-09-05 21:47:34 +0000587 source->region.height);
588 if (proceed == MagickFalse)
589 status=MagickFalse;
590 }
591 }
592 return(status);
593}
594
595/*
596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597% %
598% %
599% %
cristycc34c492010-06-26 23:49:12 +0000600% G e t I m a g e V i e w V i r t u a l I n d e x e s %
601% %
602% %
603% %
604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605%
cristy73b7d4c2010-06-27 00:31:00 +0000606% GetImageViewVirtualIndexes() returns the image view virtual indexes.
cristycc34c492010-06-26 23:49:12 +0000607%
cristy73b7d4c2010-06-27 00:31:00 +0000608% The format of the GetImageViewVirtualIndexes method is:
cristycc34c492010-06-26 23:49:12 +0000609%
610% const IndexPacket *GetImageViewVirtualIndexes(
cristy73b7d4c2010-06-27 00:31:00 +0000611% const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000612%
613% A description of each parameter follows:
614%
cristy73b7d4c2010-06-27 00:31:00 +0000615% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000616%
617*/
618MagickExport const IndexPacket *GetImageViewVirtualIndexes(
cristy73b7d4c2010-06-27 00:31:00 +0000619 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000620{
cristy73b7d4c2010-06-27 00:31:00 +0000621 assert(image_view != (ImageView *) NULL);
622 assert(image_view->signature == MagickSignature);
623 return(GetCacheViewVirtualIndexQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000624}
625
626/*
627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628% %
629% %
630% %
631% 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 %
632% %
633% %
634% %
635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636%
cristy73b7d4c2010-06-27 00:31:00 +0000637% GetImageViewVirtualPixels() returns the image view virtual pixels.
cristycc34c492010-06-26 23:49:12 +0000638%
639% The format of the GetImageViewVirtualPixels method is:
640%
cristy73b7d4c2010-06-27 00:31:00 +0000641% const PixelPacket *GetImageViewVirtualPixels(const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000642%
643% A description of each parameter follows:
644%
cristy73b7d4c2010-06-27 00:31:00 +0000645% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000646%
647*/
648MagickExport const PixelPacket *GetImageViewVirtualPixels(
cristy73b7d4c2010-06-27 00:31:00 +0000649 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000650{
cristy73b7d4c2010-06-27 00:31:00 +0000651 assert(image_view != (ImageView *) NULL);
652 assert(image_view->signature == MagickSignature);
653 return(GetCacheViewVirtualPixelQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000654}
655
656/*
657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658% %
659% %
660% %
cristy7eb1b7a2010-06-26 15:47:49 +0000661% G e t I m a g e V i e w W i d t h %
cristy3ed852e2009-09-05 21:47:34 +0000662% %
663% %
664% %
665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
666%
cristy73b7d4c2010-06-27 00:31:00 +0000667% GetImageViewWidth() returns the image view width.
cristy3ed852e2009-09-05 21:47:34 +0000668%
cristy7eb1b7a2010-06-26 15:47:49 +0000669% The format of the GetImageViewWidth method is:
cristy3ed852e2009-09-05 21:47:34 +0000670%
cristy73b7d4c2010-06-27 00:31:00 +0000671% size_t GetImageViewWidth(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000672%
673% A description of each parameter follows:
674%
cristy73b7d4c2010-06-27 00:31:00 +0000675% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000676%
677*/
cristy73b7d4c2010-06-27 00:31:00 +0000678MagickExport size_t GetImageViewWidth(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000679{
cristy73b7d4c2010-06-27 00:31:00 +0000680 assert(image_view != (ImageView *) NULL);
681 assert(image_view->signature == MagickSignature);
682 return(image_view->region.width);
cristy3ed852e2009-09-05 21:47:34 +0000683}
684
685/*
686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687% %
688% %
689% %
cristy7eb1b7a2010-06-26 15:47:49 +0000690% G e t I m a g e V i e w X %
cristy3ed852e2009-09-05 21:47:34 +0000691% %
692% %
693% %
694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695%
cristy73b7d4c2010-06-27 00:31:00 +0000696% GetImageViewX() returns the image view x offset.
cristy3ed852e2009-09-05 21:47:34 +0000697%
cristy7eb1b7a2010-06-26 15:47:49 +0000698% The format of the GetImageViewX method is:
cristy3ed852e2009-09-05 21:47:34 +0000699%
cristy73b7d4c2010-06-27 00:31:00 +0000700% ssize_t GetImageViewX(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000701%
702% A description of each parameter follows:
703%
cristy73b7d4c2010-06-27 00:31:00 +0000704% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000705%
706*/
cristy73b7d4c2010-06-27 00:31:00 +0000707MagickExport ssize_t GetImageViewX(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000708{
cristy73b7d4c2010-06-27 00:31:00 +0000709 assert(image_view != (ImageView *) NULL);
710 assert(image_view->signature == MagickSignature);
711 return(image_view->region.x);
cristy3ed852e2009-09-05 21:47:34 +0000712}
713
714/*
715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716% %
717% %
718% %
cristy7eb1b7a2010-06-26 15:47:49 +0000719% G e t I m a g e V i e w Y %
cristy3ed852e2009-09-05 21:47:34 +0000720% %
721% %
722% %
723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724%
cristy73b7d4c2010-06-27 00:31:00 +0000725% GetImageViewY() returns the image view y offset.
cristy3ed852e2009-09-05 21:47:34 +0000726%
cristy7eb1b7a2010-06-26 15:47:49 +0000727% The format of the GetImageViewY method is:
cristy3ed852e2009-09-05 21:47:34 +0000728%
cristy73b7d4c2010-06-27 00:31:00 +0000729% ssize_t GetImageViewY(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000730%
731% A description of each parameter follows:
732%
cristy73b7d4c2010-06-27 00:31:00 +0000733% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000734%
735*/
cristy73b7d4c2010-06-27 00:31:00 +0000736MagickExport ssize_t GetImageViewY(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000737{
cristy73b7d4c2010-06-27 00:31:00 +0000738 assert(image_view != (ImageView *) NULL);
739 assert(image_view->signature == MagickSignature);
740 return(image_view->region.y);
cristy3ed852e2009-09-05 21:47:34 +0000741}
742
743/*
744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745% %
746% %
747% %
cristy7eb1b7a2010-06-26 15:47:49 +0000748% I s I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000749% %
750% %
751% %
752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
753%
cristy73b7d4c2010-06-27 00:31:00 +0000754% IsImageView() returns MagickTrue if the the parameter is verified as a image
755% view object.
cristy3ed852e2009-09-05 21:47:34 +0000756%
cristy7eb1b7a2010-06-26 15:47:49 +0000757% The format of the IsImageView method is:
cristy3ed852e2009-09-05 21:47:34 +0000758%
cristy73b7d4c2010-06-27 00:31:00 +0000759% MagickBooleanType IsImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000760%
761% A description of each parameter follows:
762%
cristy73b7d4c2010-06-27 00:31:00 +0000763% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000764%
765*/
cristy73b7d4c2010-06-27 00:31:00 +0000766MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000767{
cristy73b7d4c2010-06-27 00:31:00 +0000768 if (image_view == (const ImageView *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000769 return(MagickFalse);
cristy73b7d4c2010-06-27 00:31:00 +0000770 if (image_view->signature != MagickSignature)
cristy3ed852e2009-09-05 21:47:34 +0000771 return(MagickFalse);
772 return(MagickTrue);
773}
774
775/*
776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
777% %
778% %
779% %
cristy7eb1b7a2010-06-26 15:47:49 +0000780% N e w I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000781% %
782% %
783% %
784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785%
cristy73b7d4c2010-06-27 00:31:00 +0000786% NewImageView() returns a image view required for all other methods in the
787% Image View API.
cristy3ed852e2009-09-05 21:47:34 +0000788%
cristy7eb1b7a2010-06-26 15:47:49 +0000789% The format of the NewImageView method is:
cristy3ed852e2009-09-05 21:47:34 +0000790%
cristy7eb1b7a2010-06-26 15:47:49 +0000791% ImageView *NewImageView(MagickCore *wand)
cristy3ed852e2009-09-05 21:47:34 +0000792%
793% A description of each parameter follows:
794%
795% o wand: the wand.
796%
797*/
cristy7eb1b7a2010-06-26 15:47:49 +0000798MagickExport ImageView *NewImageView(Image *image)
cristy3ed852e2009-09-05 21:47:34 +0000799{
cristy7eb1b7a2010-06-26 15:47:49 +0000800 ImageView
cristy73b7d4c2010-06-27 00:31:00 +0000801 *image_view;
cristy3ed852e2009-09-05 21:47:34 +0000802
cristy7eb1b7a2010-06-26 15:47:49 +0000803 assert(image != (Image *) NULL);
804 assert(image->signature == MagickSignature);
cristy73b7d4c2010-06-27 00:31:00 +0000805 image_view=(ImageView *) AcquireAlignedMemory(1,sizeof(*image_view));
806 if (image_view == (ImageView *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000807 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy73b7d4c2010-06-27 00:31:00 +0000808 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
809 image_view->exception=AcquireExceptionInfo();
810 image_view->image=image;
811 image_view->view=AcquireCacheView(image_view->image);
812 image_view->region.width=image->columns;
813 image_view->region.height=image->rows;
814 image_view->number_threads=GetOpenMPMaximumThreads();
815 image_view->debug=IsEventLogging();
816 image_view->signature=MagickSignature;
817 return(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000818}
819
820/*
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822% %
823% %
824% %
cristy7eb1b7a2010-06-26 15:47:49 +0000825% N e w I m a g e V i e w R e g i o n %
cristy3ed852e2009-09-05 21:47:34 +0000826% %
827% %
828% %
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830%
cristy73b7d4c2010-06-27 00:31:00 +0000831% NewImageViewRegion() returns a image view required for all other methods
832% in the Image View API.
cristy3ed852e2009-09-05 21:47:34 +0000833%
cristy7eb1b7a2010-06-26 15:47:49 +0000834% The format of the NewImageViewRegion method is:
cristy3ed852e2009-09-05 21:47:34 +0000835%
cristy7eb1b7a2010-06-26 15:47:49 +0000836% ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
cristybb503372010-05-27 20:51:26 +0000837% const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000838%
839% A description of each parameter follows:
840%
841% o wand: the magick wand.
842%
843% o x,y,columns,rows: These values define the perimeter of a region of
844% pixel_wands view.
845%
846*/
cristy7eb1b7a2010-06-26 15:47:49 +0000847MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
cristybb503372010-05-27 20:51:26 +0000848 const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000849{
cristy7eb1b7a2010-06-26 15:47:49 +0000850 ImageView
cristy73b7d4c2010-06-27 00:31:00 +0000851 *image_view;
cristy3ed852e2009-09-05 21:47:34 +0000852
cristy7eb1b7a2010-06-26 15:47:49 +0000853 assert(image != (Image *) NULL);
854 assert(image->signature == MagickSignature);
cristy73b7d4c2010-06-27 00:31:00 +0000855 image_view=(ImageView *) AcquireAlignedMemory(1,sizeof(*image_view));
856 if (image_view == (ImageView *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000857 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy73b7d4c2010-06-27 00:31:00 +0000858 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
859 image_view->exception=AcquireExceptionInfo();
860 image_view->view=AcquireCacheView(image_view->image);
861 image_view->image=image;
862 image_view->region.width=width;
863 image_view->region.height=height;
864 image_view->region.x=x;
865 image_view->region.y=y;
866 image_view->number_threads=GetOpenMPMaximumThreads();
867 image_view->debug=IsEventLogging();
868 image_view->signature=MagickSignature;
869 return(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000870}
871
872/*
873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874% %
875% %
876% %
cristy7eb1b7a2010-06-26 15:47:49 +0000877% S e t I m a g e V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +0000878% %
879% %
880% %
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882%
cristy73b7d4c2010-06-27 00:31:00 +0000883% SetImageViewIterator() iterates over the image view in parallel and calls
cristy3ed852e2009-09-05 21:47:34 +0000884% your set method for each scanline of the view. The pixel region is
885% confined to the image canvas-- that is no negative offsets or widths or
886% heights that exceed the image dimension. The pixels are initiallly
887% undefined and any settings you make in the callback method are automagically
888% synced back to your image.
889%
cristy58739472010-06-26 20:27:18 +0000890% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000891%
892% #pragma omp critical
893%
894% to define a section of code in your callback set method that must be
895% executed by a single thread at a time.
896%
cristy7eb1b7a2010-06-26 15:47:49 +0000897% The format of the SetImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000898%
cristy7eb1b7a2010-06-26 15:47:49 +0000899% MagickBooleanType SetImageViewIterator(ImageView *destination,
900% SetImageViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000901%
902% A description of each parameter follows:
903%
cristy73b7d4c2010-06-27 00:31:00 +0000904% o destination: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000905%
906% o set: the set callback method.
907%
908% o context: the user defined context.
909%
910*/
cristy7eb1b7a2010-06-26 15:47:49 +0000911MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
912 SetImageViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000913{
cristy7eb1b7a2010-06-26 15:47:49 +0000914#define SetImageViewTag "ImageView/Set"
cristy3ed852e2009-09-05 21:47:34 +0000915
916 ExceptionInfo
917 *exception;
918
919 Image
920 *destination_image;
921
cristy3ed852e2009-09-05 21:47:34 +0000922 MagickBooleanType
923 status;
924
cristycee97112010-05-28 00:44:52 +0000925 MagickOffsetType
926 progress;
927
928 ssize_t
929 y;
930
cristy7eb1b7a2010-06-26 15:47:49 +0000931 assert(destination != (ImageView *) NULL);
932 assert(destination->signature == MagickSignature);
933 if (set == (SetImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000934 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000935 destination_image=destination->image;
cristy3ed852e2009-09-05 21:47:34 +0000936 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
937 return(MagickFalse);
938 status=MagickTrue;
939 progress=0;
940 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +0000941#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy309f6132010-06-07 13:19:01 +0000942 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000943#endif
cristybb503372010-05-27 20:51:26 +0000944 for (y=destination->region.y; y < (ssize_t) destination->region.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000945 {
946 MagickBooleanType
947 sync;
948
949 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000950 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000951
cristybb503372010-05-27 20:51:26 +0000952 register ssize_t
cristycc34c492010-06-26 23:49:12 +0000953 id;
cristy3ed852e2009-09-05 21:47:34 +0000954
955 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000956 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000957
958 if (status == MagickFalse)
959 continue;
960 id=GetOpenMPThreadId();
961 pixels=GetCacheViewAuthenticPixels(destination->view,destination->region.x,
962 y,destination->region.width,1,exception);
963 if (pixels == (PixelPacket *) NULL)
964 {
965 InheritException(destination->exception,GetCacheViewException(
966 destination->view));
967 status=MagickFalse;
968 continue;
969 }
970 indexes=GetCacheViewAuthenticIndexQueue(destination->view);
971 if (set(destination,context) == MagickFalse)
972 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000973 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
974 if (sync == MagickFalse)
975 {
976 InheritException(destination->exception,GetCacheViewException(
977 destination->view));
978 status=MagickFalse;
979 }
980 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
981 {
982 MagickBooleanType
983 proceed;
984
cristyb5d5f722009-11-04 03:03:49 +0000985#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000986 #pragma omp critical (MagickCore_SetImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000987#endif
cristy7eb1b7a2010-06-26 15:47:49 +0000988 proceed=SetImageProgress(destination_image,SetImageViewTag,progress++,
cristy3ed852e2009-09-05 21:47:34 +0000989 destination->region.height);
990 if (proceed == MagickFalse)
991 status=MagickFalse;
992 }
993 }
994 return(status);
995}
996
997/*
998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999% %
1000% %
1001% %
cristy7eb1b7a2010-06-26 15:47:49 +00001002% 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 %
cristy3ed852e2009-09-05 21:47:34 +00001003% %
1004% %
1005% %
1006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1007%
cristy73b7d4c2010-06-27 00:31:00 +00001008% TransferImageViewIterator() iterates over two image views in parallel and
cristy3ed852e2009-09-05 21:47:34 +00001009% calls your transfer method for each scanline of the view. The source pixel
1010% region is not confined to the image canvas-- that is you can include
1011% negative offsets or widths or heights that exceed the image dimension.
cristy73b7d4c2010-06-27 00:31:00 +00001012% However, the destination image view is confined to the image canvas-- that
cristy3ed852e2009-09-05 21:47:34 +00001013% is no negative offsets or widths or heights that exceed the image dimension
1014% are permitted.
1015%
cristy58739472010-06-26 20:27:18 +00001016% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +00001017%
1018% #pragma omp critical
1019%
1020% to define a section of code in your callback transfer method that must be
1021% executed by a single thread at a time.
1022%
cristy7eb1b7a2010-06-26 15:47:49 +00001023% The format of the TransferImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +00001024%
cristy7eb1b7a2010-06-26 15:47:49 +00001025% MagickBooleanType TransferImageViewIterator(ImageView *source,
1026% ImageView *destination,TransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001027%
1028% A description of each parameter follows:
1029%
cristy73b7d4c2010-06-27 00:31:00 +00001030% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +00001031%
cristy73b7d4c2010-06-27 00:31:00 +00001032% o destination: the destination image view.
cristy3ed852e2009-09-05 21:47:34 +00001033%
1034% o transfer: the transfer callback method.
1035%
1036% o context: the user defined context.
1037%
1038*/
cristy7eb1b7a2010-06-26 15:47:49 +00001039MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1040 ImageView *destination,TransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001041{
cristy7eb1b7a2010-06-26 15:47:49 +00001042#define TransferImageViewTag "ImageView/Transfer"
cristy3ed852e2009-09-05 21:47:34 +00001043
1044 ExceptionInfo
1045 *exception;
1046
1047 Image
1048 *destination_image,
1049 *source_image;
1050
cristy3ed852e2009-09-05 21:47:34 +00001051 MagickBooleanType
1052 status;
1053
cristycee97112010-05-28 00:44:52 +00001054 MagickOffsetType
1055 progress;
1056
1057 ssize_t
1058 y;
1059
cristy7eb1b7a2010-06-26 15:47:49 +00001060 assert(source != (ImageView *) NULL);
1061 assert(source->signature == MagickSignature);
1062 if (transfer == (TransferImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001063 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +00001064 source_image=source->image;
1065 destination_image=destination->image;
cristy3ed852e2009-09-05 21:47:34 +00001066 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
1067 return(MagickFalse);
1068 status=MagickTrue;
1069 progress=0;
1070 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +00001071#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy309f6132010-06-07 13:19:01 +00001072 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001073#endif
cristybb503372010-05-27 20:51:26 +00001074 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001075 {
1076 MagickBooleanType
1077 sync;
1078
1079 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001080 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001081
1082 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001083 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001084
1085 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001086 *restrict destination_indexes;
cristy3ed852e2009-09-05 21:47:34 +00001087
cristybb503372010-05-27 20:51:26 +00001088 register ssize_t
cristycc34c492010-06-26 23:49:12 +00001089 id;
cristy3ed852e2009-09-05 21:47:34 +00001090
1091 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001092 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +00001093
1094 if (status == MagickFalse)
1095 continue;
1096 id=GetOpenMPThreadId();
1097 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
1098 source->region.width,1,source->exception);
1099 if (pixels == (const PixelPacket *) NULL)
1100 {
1101 status=MagickFalse;
1102 continue;
1103 }
1104 indexes=GetCacheViewVirtualIndexQueue(source->view);
cristy3ed852e2009-09-05 21:47:34 +00001105 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1106 destination->region.x,y,destination->region.width,1,exception);
1107 if (destination_pixels == (PixelPacket *) NULL)
1108 {
1109 status=MagickFalse;
1110 continue;
1111 }
1112 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
cristy3ed852e2009-09-05 21:47:34 +00001113 if (transfer(source,destination,context) == MagickFalse)
1114 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001115 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1116 if (sync == MagickFalse)
1117 {
1118 InheritException(destination->exception,GetCacheViewException(
1119 source->view));
1120 status=MagickFalse;
1121 }
1122 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1123 {
1124 MagickBooleanType
1125 proceed;
1126
cristyb5d5f722009-11-04 03:03:49 +00001127#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +00001128 #pragma omp critical (MagickCore_TransferImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001129#endif
cristy7eb1b7a2010-06-26 15:47:49 +00001130 proceed=SetImageProgress(source_image,TransferImageViewTag,progress++,
cristy3ed852e2009-09-05 21:47:34 +00001131 source->region.height);
1132 if (proceed == MagickFalse)
1133 status=MagickFalse;
1134 }
1135 }
1136 return(status);
1137}
1138
1139/*
1140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1141% %
1142% %
1143% %
cristy7eb1b7a2010-06-26 15:47:49 +00001144% U p d a t e I m a g e V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +00001145% %
1146% %
1147% %
1148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1149%
cristy73b7d4c2010-06-27 00:31:00 +00001150% UpdateImageViewIterator() iterates over the image view in parallel and calls
cristy3ed852e2009-09-05 21:47:34 +00001151% your update method for each scanline of the view. The pixel region is
1152% confined to the image canvas-- that is no negative offsets or widths or
1153% heights that exceed the image dimension are permitted. Updates to pixels
1154% in your callback are automagically synced back to the image.
1155%
cristy58739472010-06-26 20:27:18 +00001156% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +00001157%
1158% #pragma omp critical
1159%
1160% to define a section of code in your callback update method that must be
1161% executed by a single thread at a time.
1162%
cristy7eb1b7a2010-06-26 15:47:49 +00001163% The format of the UpdateImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +00001164%
cristy7eb1b7a2010-06-26 15:47:49 +00001165% MagickBooleanType UpdateImageViewIterator(ImageView *source,
1166% UpdateImageViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001167%
1168% A description of each parameter follows:
1169%
cristy73b7d4c2010-06-27 00:31:00 +00001170% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +00001171%
1172% o update: the update callback method.
1173%
1174% o context: the user defined context.
1175%
1176*/
cristy7eb1b7a2010-06-26 15:47:49 +00001177MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1178 UpdateImageViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001179{
cristy7eb1b7a2010-06-26 15:47:49 +00001180#define UpdateImageViewTag "ImageView/Update"
cristy3ed852e2009-09-05 21:47:34 +00001181
1182 ExceptionInfo
1183 *exception;
1184
1185 Image
1186 *source_image;
1187
cristy3ed852e2009-09-05 21:47:34 +00001188 MagickBooleanType
1189 status;
1190
cristycee97112010-05-28 00:44:52 +00001191 MagickOffsetType
1192 progress;
1193
1194 ssize_t
1195 y;
1196
cristy7eb1b7a2010-06-26 15:47:49 +00001197 assert(source != (ImageView *) NULL);
1198 assert(source->signature == MagickSignature);
1199 if (update == (UpdateImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001200 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +00001201 source_image=source->image;
cristy3ed852e2009-09-05 21:47:34 +00001202 if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
1203 return(MagickFalse);
1204 status=MagickTrue;
1205 progress=0;
1206 exception=source->exception;
cristyb5d5f722009-11-04 03:03:49 +00001207#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy309f6132010-06-07 13:19:01 +00001208 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001209#endif
cristybb503372010-05-27 20:51:26 +00001210 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001211 {
1212 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001213 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001214
cristy3ed852e2009-09-05 21:47:34 +00001215 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001216 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001217
cristy73b7d4c2010-06-27 00:31:00 +00001218 register ssize_t
1219 id;
1220
cristy3ed852e2009-09-05 21:47:34 +00001221 if (status == MagickFalse)
1222 continue;
1223 id=GetOpenMPThreadId();
1224 pixels=GetCacheViewAuthenticPixels(source->view,source->region.x,y,
1225 source->region.width,1,exception);
1226 if (pixels == (PixelPacket *) NULL)
1227 {
cristy73b7d4c2010-06-27 00:31:00 +00001228 InheritException(source->exception,GetCacheViewException(source->view));
cristy3ed852e2009-09-05 21:47:34 +00001229 status=MagickFalse;
1230 continue;
1231 }
1232 indexes=GetCacheViewAuthenticIndexQueue(source->view);
cristy3ed852e2009-09-05 21:47:34 +00001233 if (update(source,context) == MagickFalse)
1234 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001235 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1236 {
1237 InheritException(source->exception,GetCacheViewException(source->view));
1238 status=MagickFalse;
1239 }
1240 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1241 {
1242 MagickBooleanType
1243 proceed;
1244
cristyb5d5f722009-11-04 03:03:49 +00001245#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +00001246 #pragma omp critical (MagickCore_UpdateImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001247#endif
cristy7eb1b7a2010-06-26 15:47:49 +00001248 proceed=SetImageProgress(source_image,UpdateImageViewTag,progress++,
cristy3ed852e2009-09-05 21:47:34 +00001249 source->region.height);
1250 if (proceed == MagickFalse)
1251 status=MagickFalse;
1252 }
1253 }
1254 return(status);
1255}