blob: 1b7796cc6f02aaba4a6d7fe37ea46f8d3b7e5c14 [file] [log] [blame]
cristy16881e62012-05-06 14:41:29 +00001/*
cristy3ed852e2009-09-05 21:47:34 +00002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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% %
cristy1454be72011-12-19 01:52:48 +000025% Copyright 1999-2012 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*/
cristy4c08aed2011-07-01 19:47:50 +000048#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"
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{
cristyc3ebda22010-06-27 17:11:57 +000059 char
60 *description;
61
62 RectangleInfo
63 extent;
cristy3ed852e2009-09-05 21:47:34 +000064
cristy7eb1b7a2010-06-26 15:47:49 +000065 Image
66 *image;
cristy3ed852e2009-09-05 21:47:34 +000067
68 CacheView
69 *view;
70
cristyc3ebda22010-06-27 17:11:57 +000071 ExceptionInfo
72 *exception;
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);
cristy73bd4a52010-10-05 11:24:23 +0000110 clone_view=(ImageView *) AcquireMagickMemory(sizeof(*clone_view));
cristy7eb1b7a2010-06-26 15:47:49 +0000111 if (clone_view == (ImageView *) NULL)
112 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000113 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
cristyc3ebda22010-06-27 17:11:57 +0000114 clone_view->description=ConstantString(image_view->description);
115 clone_view->extent=image_view->extent;
116 clone_view->view=CloneCacheView(image_view->view);
cristy3ed852e2009-09-05 21:47:34 +0000117 clone_view->exception=AcquireExceptionInfo();
cristy73b7d4c2010-06-27 00:31:00 +0000118 InheritException(clone_view->exception,image_view->exception);
cristy73b7d4c2010-06-27 00:31:00 +0000119 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);
cristyc3ebda22010-06-27 17:11:57 +0000150 if (image_view->description != (char *) NULL)
151 image_view->description=DestroyString(image_view->description);
cristy73b7d4c2010-06-27 00:31:00 +0000152 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);
cristy3ed852e2009-09-05 21:47:34 +0000157}
158
159/*
160%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161% %
162% %
163% %
cristy7eb1b7a2010-06-26 15:47:49 +0000164% 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 +0000165% %
166% %
167% %
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169%
cristy73b7d4c2010-06-27 00:31:00 +0000170% DuplexTransferImageViewIterator() iterates over three image views in
cristy3ed852e2009-09-05 21:47:34 +0000171% parallel and calls your transfer method for each scanline of the view. The
cristyc3ebda22010-06-27 17:11:57 +0000172% source and duplex pixel extent is not confined to the image canvas-- that is
cristy3ed852e2009-09-05 21:47:34 +0000173% you can include negative offsets or widths or heights that exceed the image
cristy73b7d4c2010-06-27 00:31:00 +0000174% dimension. However, the destination image view is confined to the image
cristy3ed852e2009-09-05 21:47:34 +0000175% canvas-- that is no negative offsets or widths or heights that exceed the
176% image dimension are permitted.
177%
cristyd6dfc0d2010-06-27 19:30:49 +0000178% 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%
cristy58739472010-06-26 20:27:18 +0000184% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000185%
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%
cristy7eb1b7a2010-06-26 15:47:49 +0000191% The format of the DuplexTransferImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000192%
cristy7eb1b7a2010-06-26 15:47:49 +0000193% MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
194% ImageView *duplex,ImageView *destination,
195% DuplexTransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000196%
197% A description of each parameter follows:
198%
cristy73b7d4c2010-06-27 00:31:00 +0000199% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +0000200%
cristy73b7d4c2010-06-27 00:31:00 +0000201% o duplex: the duplex image view.
cristy3ed852e2009-09-05 21:47:34 +0000202%
cristy73b7d4c2010-06-27 00:31:00 +0000203% o destination: the destination image view.
cristy3ed852e2009-09-05 21:47:34 +0000204%
205% o transfer: the transfer callback method.
206%
207% o context: the user defined context.
208%
209*/
cristy7eb1b7a2010-06-26 15:47:49 +0000210MagickExport MagickBooleanType DuplexTransferImageViewIterator(
211 ImageView *source,ImageView *duplex,ImageView *destination,
212 DuplexTransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000213{
cristy3ed852e2009-09-05 21:47:34 +0000214 Image
215 *destination_image,
cristy3ed852e2009-09-05 21:47:34 +0000216 *source_image;
217
cristy3ed852e2009-09-05 21:47:34 +0000218 MagickBooleanType
219 status;
220
cristycee97112010-05-28 00:44:52 +0000221 MagickOffsetType
222 progress;
223
glennrp37618d62012-09-24 17:24:13 +0000224#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000225 size_t
226 height,
227 width;
glennrp37618d62012-09-24 17:24:13 +0000228#endif
cristyac245f82012-05-05 17:13:57 +0000229
cristycee97112010-05-28 00:44:52 +0000230 ssize_t
231 y;
232
cristy7eb1b7a2010-06-26 15:47:49 +0000233 assert(source != (ImageView *) NULL);
234 assert(source->signature == MagickSignature);
235 if (transfer == (DuplexTransferImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000236 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000237 source_image=source->image;
cristy7eb1b7a2010-06-26 15:47:49 +0000238 destination_image=destination->image;
cristy7c3af952011-10-20 16:04:16 +0000239 status=SetImageStorageClass(destination_image,DirectClass,
240 destination->exception);
241 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000242 return(MagickFalse);
243 status=MagickTrue;
244 progress=0;
glennrp37618d62012-09-24 17:24:13 +0000245#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000246 height=source->extent.height-source->extent.y;
247 width=source->extent.width-source->extent.x;
cristy9a5a52f2012-10-09 14:40:31 +0000248 #pragma omp parallel for schedule(static,4) shared(progress,status) \
cristy4ee2b0c2012-05-15 00:30:35 +0000249 dynamic_number_threads(source_image,width,height,1)
cristy3ed852e2009-09-05 21:47:34 +0000250#endif
cristyc3ebda22010-06-27 17:11:57 +0000251 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000252 {
cristy5c9e6f22010-09-17 17:31:01 +0000253 const int
254 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000255
cristy3ed852e2009-09-05 21:47:34 +0000256 MagickBooleanType
257 sync;
258
cristy4c08aed2011-07-01 19:47:50 +0000259 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +0000260 *restrict duplex_pixels,
261 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000262
cristy4c08aed2011-07-01 19:47:50 +0000263 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000264 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +0000265
266 if (status == MagickFalse)
267 continue;
cristyc3ebda22010-06-27 17:11:57 +0000268 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
269 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +0000270 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000271 {
272 status=MagickFalse;
273 continue;
274 }
cristyc3ebda22010-06-27 17:11:57 +0000275 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
276 duplex->extent.width,1,duplex->exception);
cristy4c08aed2011-07-01 19:47:50 +0000277 if (duplex_pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000278 {
279 status=MagickFalse;
280 continue;
281 }
cristy3ed852e2009-09-05 21:47:34 +0000282 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
cristy7c3af952011-10-20 16:04:16 +0000283 destination->extent.x,y,destination->extent.width,1,
284 destination->exception);
cristy4c08aed2011-07-01 19:47:50 +0000285 if (destination_pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000286 {
287 status=MagickFalse;
288 continue;
289 }
cristyc3ebda22010-06-27 17:11:57 +0000290 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000291 status=MagickFalse;
cristy7c3af952011-10-20 16:04:16 +0000292 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
cristy3ed852e2009-09-05 21:47:34 +0000293 if (sync == MagickFalse)
cristy7c3af952011-10-20 16:04:16 +0000294 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000295 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
296 {
297 MagickBooleanType
298 proceed;
299
cristyb5d5f722009-11-04 03:03:49 +0000300#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000301 #pragma omp critical (MagickCore_DuplexTransferImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000302#endif
cristyc3ebda22010-06-27 17:11:57 +0000303 proceed=SetImageProgress(source_image,source->description,progress++,
304 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000305 if (proceed == MagickFalse)
306 status=MagickFalse;
307 }
308 }
309 return(status);
310}
311
312/*
313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314% %
315% %
316% %
cristy7c3af952011-10-20 16:04:16 +0000317% 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 %
cristycc34c492010-06-26 23:49:12 +0000318% %
319% %
320% %
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322%
cristy4c08aed2011-07-01 19:47:50 +0000323% GetImageViewAuthenticMetacontent() returns the image view authentic
324% meta-content.
cristycc34c492010-06-26 23:49:12 +0000325%
326% The format of the GetImageViewAuthenticPixels method is:
327%
cristy4c08aed2011-07-01 19:47:50 +0000328% void *GetImageViewAuthenticMetacontent(
329% const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000330%
331% A description of each parameter follows:
332%
cristy73b7d4c2010-06-27 00:31:00 +0000333% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000334%
335*/
cristy4c08aed2011-07-01 19:47:50 +0000336MagickExport void *GetImageViewAuthenticMetacontent(
cristy73b7d4c2010-06-27 00:31:00 +0000337 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000338{
cristy73b7d4c2010-06-27 00:31:00 +0000339 assert(image_view != (ImageView *) NULL);
340 assert(image_view->signature == MagickSignature);
cristy4c08aed2011-07-01 19:47:50 +0000341 return(GetCacheViewAuthenticMetacontent(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000342}
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%
cristy73b7d4c2010-06-27 00:31:00 +0000355% GetImageViewAuthenticPixels() returns the image view authentic pixels.
cristycc34c492010-06-26 23:49:12 +0000356%
357% The format of the GetImageViewAuthenticPixels method is:
358%
cristy4c08aed2011-07-01 19:47:50 +0000359% Quantum *GetImageViewAuthenticPixels(const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000360%
361% A description of each parameter follows:
362%
cristy73b7d4c2010-06-27 00:31:00 +0000363% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000364%
365*/
cristy4c08aed2011-07-01 19:47:50 +0000366MagickExport Quantum *GetImageViewAuthenticPixels(
cristy73b7d4c2010-06-27 00:31:00 +0000367 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000368{
cristy73b7d4c2010-06-27 00:31:00 +0000369 assert(image_view != (ImageView *) NULL);
370 assert(image_view->signature == MagickSignature);
371 return(GetCacheViewAuthenticPixelQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000372}
373
374/*
375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376% %
377% %
378% %
cristy7eb1b7a2010-06-26 15:47:49 +0000379% 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 +0000380% %
381% %
382% %
383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384%
cristy7eb1b7a2010-06-26 15:47:49 +0000385% GetImageViewException() returns the severity, reason, and description of any
cristy73b7d4c2010-06-27 00:31:00 +0000386% error that occurs when utilizing a image view.
cristy3ed852e2009-09-05 21:47:34 +0000387%
cristy7eb1b7a2010-06-26 15:47:49 +0000388% The format of the GetImageViewException method is:
cristy3ed852e2009-09-05 21:47:34 +0000389%
cristy73b7d4c2010-06-27 00:31:00 +0000390% char *GetImageViewException(const PixelImage *image_view,
cristy3ed852e2009-09-05 21:47:34 +0000391% ExceptionType *severity)
392%
393% A description of each parameter follows:
394%
cristy73b7d4c2010-06-27 00:31:00 +0000395% o image_view: the pixel image_view.
cristy3ed852e2009-09-05 21:47:34 +0000396%
397% o severity: the severity of the error is returned here.
398%
399*/
cristy73b7d4c2010-06-27 00:31:00 +0000400MagickExport char *GetImageViewException(const ImageView *image_view,
cristy3ed852e2009-09-05 21:47:34 +0000401 ExceptionType *severity)
402{
403 char
404 *description;
405
cristy73b7d4c2010-06-27 00:31:00 +0000406 assert(image_view != (const ImageView *) NULL);
407 assert(image_view->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +0000408 assert(severity != (ExceptionType *) NULL);
cristy73b7d4c2010-06-27 00:31:00 +0000409 *severity=image_view->exception->severity;
cristy3ed852e2009-09-05 21:47:34 +0000410 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
411 sizeof(*description));
412 if (description == (char *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000413 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000414 *description='\0';
cristy73b7d4c2010-06-27 00:31:00 +0000415 if (image_view->exception->reason != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000416 (void) CopyMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000417 image_view->exception->severity,image_view->exception->reason),
cristy3ed852e2009-09-05 21:47:34 +0000418 MaxTextExtent);
cristy73b7d4c2010-06-27 00:31:00 +0000419 if (image_view->exception->description != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000420 {
421 (void) ConcatenateMagickString(description," (",MaxTextExtent);
422 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000423 image_view->exception->severity,image_view->exception->description),
cristy3ed852e2009-09-05 21:47:34 +0000424 MaxTextExtent);
425 (void) ConcatenateMagickString(description,")",MaxTextExtent);
426 }
427 return(description);
428}
429
430/*
431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432% %
433% %
434% %
cristyc3ebda22010-06-27 17:11:57 +0000435% G e t I m a g e V i e w E x t e n t %
cristy3ed852e2009-09-05 21:47:34 +0000436% %
437% %
438% %
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440%
cristyc3ebda22010-06-27 17:11:57 +0000441% GetImageViewExtent() returns the image view extent.
cristy3ed852e2009-09-05 21:47:34 +0000442%
cristyc3ebda22010-06-27 17:11:57 +0000443% The format of the GetImageViewExtent method is:
cristy3ed852e2009-09-05 21:47:34 +0000444%
cristyc3ebda22010-06-27 17:11:57 +0000445% RectangleInfo GetImageViewExtent(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000446%
447% A description of each parameter follows:
448%
cristy73b7d4c2010-06-27 00:31:00 +0000449% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000450%
451*/
cristyc3ebda22010-06-27 17:11:57 +0000452MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000453{
cristy73b7d4c2010-06-27 00:31:00 +0000454 assert(image_view != (ImageView *) NULL);
455 assert(image_view->signature == MagickSignature);
cristyc3ebda22010-06-27 17:11:57 +0000456 return(image_view->extent);
cristy73b7d4c2010-06-27 00:31:00 +0000457}
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);
cristy3ed852e2009-09-05 21:47:34 +0000486}
487
488/*
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490% %
491% %
492% %
cristy7eb1b7a2010-06-26 15:47:49 +0000493% 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 +0000494% %
495% %
496% %
497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498%
cristy73b7d4c2010-06-27 00:31:00 +0000499% GetImageViewIterator() iterates over the image view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +0000500% your get method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +0000501% 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%
cristyd6dfc0d2010-06-27 19:30:49 +0000505% The callback signature is:
506%
507% MagickBooleanType GetImageViewMethod(const ImageView *source,
508% const ssize_t y,const int thread_id,void *context)
509%
cristy58739472010-06-26 20:27:18 +0000510% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000511%
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%
cristy7eb1b7a2010-06-26 15:47:49 +0000517% The format of the GetImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000518%
cristy7eb1b7a2010-06-26 15:47:49 +0000519% MagickBooleanType GetImageViewIterator(ImageView *source,
520% GetImageViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000521%
522% A description of each parameter follows:
523%
cristy73b7d4c2010-06-27 00:31:00 +0000524% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +0000525%
526% o get: the get callback method.
527%
528% o context: the user defined context.
529%
530*/
cristy7eb1b7a2010-06-26 15:47:49 +0000531MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
532 GetImageViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000533{
cristy3ed852e2009-09-05 21:47:34 +0000534 Image
535 *source_image;
536
cristy3ed852e2009-09-05 21:47:34 +0000537 MagickBooleanType
538 status;
539
cristycee97112010-05-28 00:44:52 +0000540 MagickOffsetType
541 progress;
542
glennrp37618d62012-09-24 17:24:13 +0000543#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000544 size_t
545 height,
546 width;
glennrp37618d62012-09-24 17:24:13 +0000547#endif
cristyac245f82012-05-05 17:13:57 +0000548
cristycee97112010-05-28 00:44:52 +0000549 ssize_t
550 y;
551
cristy7eb1b7a2010-06-26 15:47:49 +0000552 assert(source != (ImageView *) NULL);
553 assert(source->signature == MagickSignature);
554 if (get == (GetImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000555 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000556 source_image=source->image;
cristy3ed852e2009-09-05 21:47:34 +0000557 status=MagickTrue;
558 progress=0;
glennrp9d9f0e52012-09-24 18:13:12 +0000559#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000560 height=source->extent.height-source->extent.y;
561 width=source->extent.width-source->extent.x;
cristy9a5a52f2012-10-09 14:40:31 +0000562 #pragma omp parallel for schedule(static,4) shared(progress,status) \
cristy4ee2b0c2012-05-15 00:30:35 +0000563 dynamic_number_threads(source_image,width,height,1)
cristy3ed852e2009-09-05 21:47:34 +0000564#endif
cristyc3ebda22010-06-27 17:11:57 +0000565 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000566 {
cristy5c9e6f22010-09-17 17:31:01 +0000567 const int
568 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000569
cristy4c08aed2011-07-01 19:47:50 +0000570 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000571 *pixels;
572
cristy3ed852e2009-09-05 21:47:34 +0000573 if (status == MagickFalse)
574 continue;
cristyc3ebda22010-06-27 17:11:57 +0000575 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
576 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +0000577 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000578 {
579 status=MagickFalse;
580 continue;
581 }
cristyd6dfc0d2010-06-27 19:30:49 +0000582 if (get(source,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000583 status=MagickFalse;
584 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
585 {
586 MagickBooleanType
587 proceed;
588
cristyb5d5f722009-11-04 03:03:49 +0000589#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000590 #pragma omp critical (MagickCore_GetImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000591#endif
cristyc3ebda22010-06-27 17:11:57 +0000592 proceed=SetImageProgress(source_image,source->description,progress++,
593 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000594 if (proceed == MagickFalse)
595 status=MagickFalse;
596 }
597 }
598 return(status);
599}
600
601/*
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603% %
604% %
605% %
cristy4c08aed2011-07-01 19:47:50 +0000606% 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 %
cristycc34c492010-06-26 23:49:12 +0000607% %
608% %
609% %
610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611%
cristy4c08aed2011-07-01 19:47:50 +0000612% GetImageViewVirtualMetacontent() returns the image view virtual
613% meta-content.
cristycc34c492010-06-26 23:49:12 +0000614%
cristy4c08aed2011-07-01 19:47:50 +0000615% The format of the GetImageViewVirtualMetacontent method is:
cristycc34c492010-06-26 23:49:12 +0000616%
cristy4c08aed2011-07-01 19:47:50 +0000617% const void *GetImageViewVirtualMetacontent(
cristy73b7d4c2010-06-27 00:31:00 +0000618% const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000619%
620% A description of each parameter follows:
621%
cristy73b7d4c2010-06-27 00:31:00 +0000622% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000623%
624*/
cristy4c08aed2011-07-01 19:47:50 +0000625MagickExport const void *GetImageViewVirtualMetacontent(
cristy73b7d4c2010-06-27 00:31:00 +0000626 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000627{
cristy73b7d4c2010-06-27 00:31:00 +0000628 assert(image_view != (ImageView *) NULL);
629 assert(image_view->signature == MagickSignature);
cristy4c08aed2011-07-01 19:47:50 +0000630 return(GetCacheViewVirtualMetacontent(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000631}
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%
cristy73b7d4c2010-06-27 00:31:00 +0000644% GetImageViewVirtualPixels() returns the image view virtual pixels.
cristycc34c492010-06-26 23:49:12 +0000645%
646% The format of the GetImageViewVirtualPixels method is:
647%
cristy4c08aed2011-07-01 19:47:50 +0000648% const Quantum *GetImageViewVirtualPixels(const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000649%
650% A description of each parameter follows:
651%
cristy73b7d4c2010-06-27 00:31:00 +0000652% o image_view: the image view.
cristycc34c492010-06-26 23:49:12 +0000653%
654*/
cristy4c08aed2011-07-01 19:47:50 +0000655MagickExport const Quantum *GetImageViewVirtualPixels(
cristy73b7d4c2010-06-27 00:31:00 +0000656 const ImageView *image_view)
cristycc34c492010-06-26 23:49:12 +0000657{
cristy73b7d4c2010-06-27 00:31:00 +0000658 assert(image_view != (ImageView *) NULL);
659 assert(image_view->signature == MagickSignature);
660 return(GetCacheViewVirtualPixelQueue(image_view->view));
cristycc34c492010-06-26 23:49:12 +0000661}
662
663/*
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665% %
666% %
667% %
cristy7eb1b7a2010-06-26 15:47:49 +0000668% I s I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000669% %
670% %
671% %
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673%
cristy73b7d4c2010-06-27 00:31:00 +0000674% IsImageView() returns MagickTrue if the the parameter is verified as a image
675% view object.
cristy3ed852e2009-09-05 21:47:34 +0000676%
cristy7eb1b7a2010-06-26 15:47:49 +0000677% The format of the IsImageView method is:
cristy3ed852e2009-09-05 21:47:34 +0000678%
cristy73b7d4c2010-06-27 00:31:00 +0000679% MagickBooleanType IsImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000680%
681% A description of each parameter follows:
682%
cristy73b7d4c2010-06-27 00:31:00 +0000683% o image_view: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000684%
685*/
cristy73b7d4c2010-06-27 00:31:00 +0000686MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
cristy3ed852e2009-09-05 21:47:34 +0000687{
cristy73b7d4c2010-06-27 00:31:00 +0000688 if (image_view == (const ImageView *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000689 return(MagickFalse);
cristy73b7d4c2010-06-27 00:31:00 +0000690 if (image_view->signature != MagickSignature)
cristy3ed852e2009-09-05 21:47:34 +0000691 return(MagickFalse);
692 return(MagickTrue);
693}
694
695/*
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697% %
698% %
699% %
cristy7eb1b7a2010-06-26 15:47:49 +0000700% N e w I m a g e V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000701% %
702% %
703% %
704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
705%
cristy73b7d4c2010-06-27 00:31:00 +0000706% NewImageView() returns a image view required for all other methods in the
707% Image View API.
cristy3ed852e2009-09-05 21:47:34 +0000708%
cristy7eb1b7a2010-06-26 15:47:49 +0000709% The format of the NewImageView method is:
cristy3ed852e2009-09-05 21:47:34 +0000710%
cristydb070952012-04-20 14:33:00 +0000711% ImageView *NewImageView(MagickCore *wand,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000712%
713% A description of each parameter follows:
714%
cristydb070952012-04-20 14:33:00 +0000715% o image: the image.
716%
717% o exception: return any errors or warnings in this structure.
cristy3ed852e2009-09-05 21:47:34 +0000718%
719*/
cristydb070952012-04-20 14:33:00 +0000720MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000721{
cristy7eb1b7a2010-06-26 15:47:49 +0000722 ImageView
cristy73b7d4c2010-06-27 00:31:00 +0000723 *image_view;
cristy3ed852e2009-09-05 21:47:34 +0000724
cristy7eb1b7a2010-06-26 15:47:49 +0000725 assert(image != (Image *) NULL);
726 assert(image->signature == MagickSignature);
cristy73bd4a52010-10-05 11:24:23 +0000727 image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
cristy73b7d4c2010-06-27 00:31:00 +0000728 if (image_view == (ImageView *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000729 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy73b7d4c2010-06-27 00:31:00 +0000730 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
cristyc3ebda22010-06-27 17:11:57 +0000731 image_view->description=ConstantString("ImageView");
cristy73b7d4c2010-06-27 00:31:00 +0000732 image_view->image=image;
cristydb070952012-04-20 14:33:00 +0000733 image_view->view=AcquireVirtualCacheView(image_view->image,exception);
cristyc3ebda22010-06-27 17:11:57 +0000734 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;
cristyc3ebda22010-06-27 17:11:57 +0000738 image_view->exception=AcquireExceptionInfo();
cristy73b7d4c2010-06-27 00:31:00 +0000739 image_view->debug=IsEventLogging();
740 image_view->signature=MagickSignature;
741 return(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000742}
743
744/*
745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746% %
747% %
748% %
cristy7eb1b7a2010-06-26 15:47:49 +0000749% N e w I m a g e V i e w R e g i o n %
cristy3ed852e2009-09-05 21:47:34 +0000750% %
751% %
752% %
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754%
cristy73b7d4c2010-06-27 00:31:00 +0000755% NewImageViewRegion() returns a image view required for all other methods
756% in the Image View API.
cristy3ed852e2009-09-05 21:47:34 +0000757%
cristy7eb1b7a2010-06-26 15:47:49 +0000758% The format of the NewImageViewRegion method is:
cristy3ed852e2009-09-05 21:47:34 +0000759%
cristy7eb1b7a2010-06-26 15:47:49 +0000760% ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
cristydb070952012-04-20 14:33:00 +0000761% const ssize_t y,const size_t width,const size_t height,
762% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000763%
764% A description of each parameter follows:
765%
766% o wand: the magick wand.
767%
cristyc3ebda22010-06-27 17:11:57 +0000768% o x,y,columns,rows: These values define the perimeter of a extent of
cristy3ed852e2009-09-05 21:47:34 +0000769% pixel_wands view.
770%
cristydb070952012-04-20 14:33:00 +0000771% o exception: return any errors or warnings in this structure.
772%
cristy3ed852e2009-09-05 21:47:34 +0000773*/
cristy7eb1b7a2010-06-26 15:47:49 +0000774MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
cristydb070952012-04-20 14:33:00 +0000775 const ssize_t y,const size_t width,const size_t height,
776 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000777{
cristy7eb1b7a2010-06-26 15:47:49 +0000778 ImageView
cristy73b7d4c2010-06-27 00:31:00 +0000779 *image_view;
cristy3ed852e2009-09-05 21:47:34 +0000780
cristy7eb1b7a2010-06-26 15:47:49 +0000781 assert(image != (Image *) NULL);
782 assert(image->signature == MagickSignature);
cristy73bd4a52010-10-05 11:24:23 +0000783 image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
cristy73b7d4c2010-06-27 00:31:00 +0000784 if (image_view == (ImageView *) NULL)
cristy7eb1b7a2010-06-26 15:47:49 +0000785 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy73b7d4c2010-06-27 00:31:00 +0000786 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
cristyc3ebda22010-06-27 17:11:57 +0000787 image_view->description=ConstantString("ImageView");
cristydb070952012-04-20 14:33:00 +0000788 image_view->view=AcquireVirtualCacheView(image_view->image,exception);
cristy73b7d4c2010-06-27 00:31:00 +0000789 image_view->image=image;
cristyc3ebda22010-06-27 17:11:57 +0000790 image_view->extent.width=width;
791 image_view->extent.height=height;
792 image_view->extent.x=x;
793 image_view->extent.y=y;
cristyc3ebda22010-06-27 17:11:57 +0000794 image_view->exception=AcquireExceptionInfo();
cristy73b7d4c2010-06-27 00:31:00 +0000795 image_view->debug=IsEventLogging();
796 image_view->signature=MagickSignature;
797 return(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000798}
799
800/*
801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802% %
803% %
804% %
cristyc3ebda22010-06-27 17:11:57 +0000805% 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% %
cristy7eb1b7a2010-06-26 15:47:49 +0000838% 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 +0000839% %
840% %
841% %
842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843%
cristy73b7d4c2010-06-27 00:31:00 +0000844% SetImageViewIterator() iterates over the image view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +0000845% your set method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +0000846% 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%
cristyd6dfc0d2010-06-27 19:30:49 +0000851% The callback signature is:
852%
853% MagickBooleanType SetImageViewMethod(ImageView *destination,
854% const ssize_t y,const int thread_id,void *context)
855%
cristy58739472010-06-26 20:27:18 +0000856% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000857%
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%
cristy7eb1b7a2010-06-26 15:47:49 +0000863% The format of the SetImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000864%
cristy7eb1b7a2010-06-26 15:47:49 +0000865% MagickBooleanType SetImageViewIterator(ImageView *destination,
866% SetImageViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000867%
868% A description of each parameter follows:
869%
cristy73b7d4c2010-06-27 00:31:00 +0000870% o destination: the image view.
cristy3ed852e2009-09-05 21:47:34 +0000871%
872% o set: the set callback method.
873%
874% o context: the user defined context.
875%
876*/
cristy7eb1b7a2010-06-26 15:47:49 +0000877MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
878 SetImageViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000879{
cristy3ed852e2009-09-05 21:47:34 +0000880 Image
881 *destination_image;
882
cristy3ed852e2009-09-05 21:47:34 +0000883 MagickBooleanType
884 status;
885
cristycee97112010-05-28 00:44:52 +0000886 MagickOffsetType
887 progress;
888
glennrp37618d62012-09-24 17:24:13 +0000889#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000890 size_t
891 height,
892 width;
glennrp37618d62012-09-24 17:24:13 +0000893#endif
cristyac245f82012-05-05 17:13:57 +0000894
cristycee97112010-05-28 00:44:52 +0000895 ssize_t
896 y;
897
cristy7eb1b7a2010-06-26 15:47:49 +0000898 assert(destination != (ImageView *) NULL);
899 assert(destination->signature == MagickSignature);
900 if (set == (SetImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000901 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000902 destination_image=destination->image;
cristy7c3af952011-10-20 16:04:16 +0000903 status=SetImageStorageClass(destination_image,DirectClass,
904 destination->exception);
905 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000906 return(MagickFalse);
907 status=MagickTrue;
908 progress=0;
glennrp37618d62012-09-24 17:24:13 +0000909#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000910 height=destination->extent.height-destination->extent.y;
911 width=destination->extent.width-destination->extent.x;
cristy9a5a52f2012-10-09 14:40:31 +0000912 #pragma omp parallel for schedule(static,4) shared(progress,status) \
cristy4ee2b0c2012-05-15 00:30:35 +0000913 dynamic_number_threads(destination_image,width,height,1)
cristy3ed852e2009-09-05 21:47:34 +0000914#endif
cristyc3ebda22010-06-27 17:11:57 +0000915 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000916 {
cristy5c9e6f22010-09-17 17:31:01 +0000917 const int
918 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000919
cristy3ed852e2009-09-05 21:47:34 +0000920 MagickBooleanType
921 sync;
922
cristy4c08aed2011-07-01 19:47:50 +0000923 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000924 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000925
926 if (status == MagickFalse)
927 continue;
cristyc3ebda22010-06-27 17:11:57 +0000928 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
cristy7c3af952011-10-20 16:04:16 +0000929 y,destination->extent.width,1,destination->exception);
cristy4c08aed2011-07-01 19:47:50 +0000930 if (pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000931 {
cristy3ed852e2009-09-05 21:47:34 +0000932 status=MagickFalse;
933 continue;
934 }
cristyd6dfc0d2010-06-27 19:30:49 +0000935 if (set(destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000936 status=MagickFalse;
cristy7c3af952011-10-20 16:04:16 +0000937 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
cristy3ed852e2009-09-05 21:47:34 +0000938 if (sync == MagickFalse)
cristy7c3af952011-10-20 16:04:16 +0000939 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000940 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
941 {
942 MagickBooleanType
943 proceed;
944
cristyb5d5f722009-11-04 03:03:49 +0000945#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +0000946 #pragma omp critical (MagickCore_SetImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000947#endif
cristyc3ebda22010-06-27 17:11:57 +0000948 proceed=SetImageProgress(destination_image,destination->description,
949 progress++,destination->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000950 if (proceed == MagickFalse)
951 status=MagickFalse;
952 }
953 }
954 return(status);
955}
956
957/*
958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959% %
960% %
961% %
cristy7eb1b7a2010-06-26 15:47:49 +0000962% 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 +0000963% %
964% %
965% %
966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
967%
cristy73b7d4c2010-06-27 00:31:00 +0000968% TransferImageViewIterator() iterates over two image views in parallel and
cristy3ed852e2009-09-05 21:47:34 +0000969% calls your transfer method for each scanline of the view. The source pixel
cristyc3ebda22010-06-27 17:11:57 +0000970% extent is not confined to the image canvas-- that is you can include
cristy3ed852e2009-09-05 21:47:34 +0000971% negative offsets or widths or heights that exceed the image dimension.
cristy73b7d4c2010-06-27 00:31:00 +0000972% However, the destination image view is confined to the image canvas-- that
cristy3ed852e2009-09-05 21:47:34 +0000973% is no negative offsets or widths or heights that exceed the image dimension
974% are permitted.
975%
cristyd6dfc0d2010-06-27 19:30:49 +0000976% 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%
cristy58739472010-06-26 20:27:18 +0000982% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000983%
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%
cristy7eb1b7a2010-06-26 15:47:49 +0000989% The format of the TransferImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000990%
cristy7eb1b7a2010-06-26 15:47:49 +0000991% MagickBooleanType TransferImageViewIterator(ImageView *source,
992% ImageView *destination,TransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000993%
994% A description of each parameter follows:
995%
cristy73b7d4c2010-06-27 00:31:00 +0000996% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +0000997%
cristy73b7d4c2010-06-27 00:31:00 +0000998% o destination: the destination image view.
cristy3ed852e2009-09-05 21:47:34 +0000999%
1000% o transfer: the transfer callback method.
1001%
1002% o context: the user defined context.
1003%
1004*/
cristy7eb1b7a2010-06-26 15:47:49 +00001005MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1006 ImageView *destination,TransferImageViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001007{
cristy3ed852e2009-09-05 21:47:34 +00001008 Image
1009 *destination_image,
1010 *source_image;
1011
cristy3ed852e2009-09-05 21:47:34 +00001012 MagickBooleanType
1013 status;
1014
cristycee97112010-05-28 00:44:52 +00001015 MagickOffsetType
1016 progress;
1017
glennrp37618d62012-09-24 17:24:13 +00001018#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001019 size_t
1020 height,
1021 width;
glennrp37618d62012-09-24 17:24:13 +00001022#endif
cristyac245f82012-05-05 17:13:57 +00001023
cristycee97112010-05-28 00:44:52 +00001024 ssize_t
1025 y;
1026
cristy7eb1b7a2010-06-26 15:47:49 +00001027 assert(source != (ImageView *) NULL);
1028 assert(source->signature == MagickSignature);
1029 if (transfer == (TransferImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001030 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +00001031 source_image=source->image;
1032 destination_image=destination->image;
cristy7c3af952011-10-20 16:04:16 +00001033 status=SetImageStorageClass(destination_image,DirectClass,
1034 destination->exception);
1035 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001036 return(MagickFalse);
1037 status=MagickTrue;
1038 progress=0;
glennrp37618d62012-09-24 17:24:13 +00001039#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001040 height=source->extent.height-source->extent.y;
1041 width=source->extent.width-source->extent.x;
cristy9a5a52f2012-10-09 14:40:31 +00001042 #pragma omp parallel for schedule(static,4) shared(progress,status) \
cristy4ee2b0c2012-05-15 00:30:35 +00001043 dynamic_number_threads(source_image,width,height,1)
cristy3ed852e2009-09-05 21:47:34 +00001044#endif
cristyc3ebda22010-06-27 17:11:57 +00001045 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001046 {
cristy5c9e6f22010-09-17 17:31:01 +00001047 const int
1048 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +00001049
cristy3ed852e2009-09-05 21:47:34 +00001050 MagickBooleanType
1051 sync;
1052
cristy4c08aed2011-07-01 19:47:50 +00001053 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001054 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001055
cristy4c08aed2011-07-01 19:47:50 +00001056 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001057 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +00001058
1059 if (status == MagickFalse)
1060 continue;
cristyc3ebda22010-06-27 17:11:57 +00001061 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1062 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +00001063 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001064 {
1065 status=MagickFalse;
1066 continue;
1067 }
cristy3ed852e2009-09-05 21:47:34 +00001068 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
cristy7c3af952011-10-20 16:04:16 +00001069 destination->extent.x,y,destination->extent.width,1,
1070 destination->exception);
cristy4c08aed2011-07-01 19:47:50 +00001071 if (destination_pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001072 {
1073 status=MagickFalse;
1074 continue;
1075 }
cristyc3ebda22010-06-27 17:11:57 +00001076 if (transfer(source,destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001077 status=MagickFalse;
cristy7c3af952011-10-20 16:04:16 +00001078 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
cristy3ed852e2009-09-05 21:47:34 +00001079 if (sync == MagickFalse)
cristy7c3af952011-10-20 16:04:16 +00001080 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001081 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1082 {
1083 MagickBooleanType
1084 proceed;
1085
cristyb5d5f722009-11-04 03:03:49 +00001086#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001087 #pragma omp critical (MagickCore_TransferImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001088#endif
cristyc3ebda22010-06-27 17:11:57 +00001089 proceed=SetImageProgress(source_image,source->description,progress++,
1090 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +00001091 if (proceed == MagickFalse)
1092 status=MagickFalse;
1093 }
1094 }
1095 return(status);
1096}
1097
1098/*
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100% %
1101% %
1102% %
cristy7eb1b7a2010-06-26 15:47:49 +00001103% 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 +00001104% %
1105% %
1106% %
1107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108%
cristy73b7d4c2010-06-27 00:31:00 +00001109% UpdateImageViewIterator() iterates over the image view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +00001110% your update method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +00001111% 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%
cristyd6dfc0d2010-06-27 19:30:49 +00001115% The callback signature is:
1116%
1117% MagickBooleanType UpdateImageViewMethod(ImageView *source,
1118% const ssize_t y,const int thread_id,void *context)
1119%
cristy58739472010-06-26 20:27:18 +00001120% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +00001121%
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%
cristy7eb1b7a2010-06-26 15:47:49 +00001127% The format of the UpdateImageViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +00001128%
cristy7eb1b7a2010-06-26 15:47:49 +00001129% MagickBooleanType UpdateImageViewIterator(ImageView *source,
1130% UpdateImageViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001131%
1132% A description of each parameter follows:
1133%
cristy73b7d4c2010-06-27 00:31:00 +00001134% o source: the source image view.
cristy3ed852e2009-09-05 21:47:34 +00001135%
1136% o update: the update callback method.
1137%
1138% o context: the user defined context.
1139%
1140*/
cristy7eb1b7a2010-06-26 15:47:49 +00001141MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1142 UpdateImageViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001143{
cristy3ed852e2009-09-05 21:47:34 +00001144 Image
1145 *source_image;
1146
cristy3ed852e2009-09-05 21:47:34 +00001147 MagickBooleanType
1148 status;
1149
cristycee97112010-05-28 00:44:52 +00001150 MagickOffsetType
1151 progress;
1152
glennrp37618d62012-09-24 17:24:13 +00001153#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001154 size_t
1155 height,
1156 width;
glennrp37618d62012-09-24 17:24:13 +00001157#endif
cristyac245f82012-05-05 17:13:57 +00001158
cristycee97112010-05-28 00:44:52 +00001159 ssize_t
1160 y;
1161
cristy7eb1b7a2010-06-26 15:47:49 +00001162 assert(source != (ImageView *) NULL);
1163 assert(source->signature == MagickSignature);
1164 if (update == (UpdateImageViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001165 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +00001166 source_image=source->image;
cristy7c3af952011-10-20 16:04:16 +00001167 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1168 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001169 return(MagickFalse);
1170 status=MagickTrue;
1171 progress=0;
glennrp37618d62012-09-24 17:24:13 +00001172#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001173 height=source->extent.height-source->extent.y;
1174 width=source->extent.width-source->extent.x;
cristy9a5a52f2012-10-09 14:40:31 +00001175 #pragma omp parallel for schedule(static,4) shared(progress,status) \
cristy4ee2b0c2012-05-15 00:30:35 +00001176 dynamic_number_threads(source_image,width,height,1)
cristy3ed852e2009-09-05 21:47:34 +00001177#endif
cristyc3ebda22010-06-27 17:11:57 +00001178 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001179 {
cristy5c9e6f22010-09-17 17:31:01 +00001180 const int
1181 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +00001182
cristy4c08aed2011-07-01 19:47:50 +00001183 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001184 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001185
1186 if (status == MagickFalse)
1187 continue;
cristyc3ebda22010-06-27 17:11:57 +00001188 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
cristy7c3af952011-10-20 16:04:16 +00001189 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +00001190 if (pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001191 {
cristy3ed852e2009-09-05 21:47:34 +00001192 status=MagickFalse;
1193 continue;
1194 }
cristyc3ebda22010-06-27 17:11:57 +00001195 if (update(source,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001196 status=MagickFalse;
cristy7c3af952011-10-20 16:04:16 +00001197 status=SyncCacheViewAuthenticPixels(source->view,source->exception);
1198 if (status == MagickFalse)
1199 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001200 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1201 {
1202 MagickBooleanType
1203 proceed;
1204
cristyb5d5f722009-11-04 03:03:49 +00001205#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyac245f82012-05-05 17:13:57 +00001206 #pragma omp critical (MagickCore_UpdateImageViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001207#endif
cristyc3ebda22010-06-27 17:11:57 +00001208 proceed=SetImageProgress(source_image,source->description,progress++,
1209 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +00001210 if (proceed == MagickFalse)
1211 status=MagickFalse;
1212 }
1213 }
1214 return(status);
1215}