blob: 83b024e307643bffa4722b45a99058eba49ca4e9 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
cristy58739472010-06-26 20:27:18 +00005% W W AAA N N DDDD %
6% W W A A NN N D D %
7% W W W AAAAA N N N D D %
8% WW WW A A N NN D D %
9% W W A A N N DDDD %
cristy3ed852e2009-09-05 21:47:34 +000010% %
11% V V IIIII EEEEE W W %
12% V V I E W W %
13% V V I EEE W W W %
14% V V I E WW WW %
15% V IIIII EEEEE W W %
16% %
17% %
cristy7eb1b7a2010-06-26 15:47:49 +000018% MagickWand Wand View Methods %
cristy3ed852e2009-09-05 21:47:34 +000019% %
20% Software Design %
21% John Cristy %
22% March 2003 %
23% %
24% %
cristy7e41fe82010-12-04 23:12:08 +000025% Copyright 1999-2011 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 "MagickWand/studio.h"
49#include "MagickWand/MagickWand.h"
50#include "MagickWand/magick-wand-private.h"
51#include "MagickWand/wand.h"
52#include "MagickCore/monitor-private.h"
53#include "MagickCore/thread-private.h"
cristy3ed852e2009-09-05 21:47:34 +000054/*
55 Define declarations.
56*/
cristy7eb1b7a2010-06-26 15:47:49 +000057#define WandViewId "WandView"
cristy3ed852e2009-09-05 21:47:34 +000058
59/*
60 Typedef declarations.
61*/
cristy7eb1b7a2010-06-26 15:47:49 +000062struct _WandView
cristy3ed852e2009-09-05 21:47:34 +000063{
cristybb503372010-05-27 20:51:26 +000064 size_t
cristy3ed852e2009-09-05 21:47:34 +000065 id;
66
67 char
cristyc3ebda22010-06-27 17:11:57 +000068 name[MaxTextExtent],
69 *description;
cristy3ed852e2009-09-05 21:47:34 +000070
cristyc3ebda22010-06-27 17:11:57 +000071 RectangleInfo
72 extent;
cristy3ed852e2009-09-05 21:47:34 +000073
74 MagickWand
75 *wand;
76
cristy4c08aed2011-07-01 19:47:50 +000077 Image
78 *image;
79
cristy3ed852e2009-09-05 21:47:34 +000080 CacheView
81 *view;
82
cristybb503372010-05-27 20:51:26 +000083 size_t
cristy3ed852e2009-09-05 21:47:34 +000084 number_threads;
85
86 PixelWand
87 ***pixel_wands;
88
cristyc3ebda22010-06-27 17:11:57 +000089 ExceptionInfo
90 *exception;
91
cristy3ed852e2009-09-05 21:47:34 +000092 MagickBooleanType
93 debug;
94
cristybb503372010-05-27 20:51:26 +000095 size_t
cristy3ed852e2009-09-05 21:47:34 +000096 signature;
97};
98
99/*
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
cristy7eb1b7a2010-06-26 15:47:49 +0000104% C l o n e W a n d V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
cristy73b7d4c2010-06-27 00:31:00 +0000110% CloneWandView() makes a copy of the specified wand view.
cristy3ed852e2009-09-05 21:47:34 +0000111%
cristy7eb1b7a2010-06-26 15:47:49 +0000112% The format of the CloneWandView method is:
cristy3ed852e2009-09-05 21:47:34 +0000113%
cristy73b7d4c2010-06-27 00:31:00 +0000114% WandView *CloneWandView(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000115%
116% A description of each parameter follows:
117%
cristy73b7d4c2010-06-27 00:31:00 +0000118% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000119%
120*/
cristy73b7d4c2010-06-27 00:31:00 +0000121WandExport WandView *CloneWandView(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000122{
cristy7eb1b7a2010-06-26 15:47:49 +0000123 WandView
cristy3ed852e2009-09-05 21:47:34 +0000124 *clone_view;
125
cristybb503372010-05-27 20:51:26 +0000126 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000127 i;
128
cristy73b7d4c2010-06-27 00:31:00 +0000129 assert(wand_view != (WandView *) NULL);
130 assert(wand_view->signature == WandSignature);
131 if (wand_view->debug != MagickFalse)
132 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
cristy73bd4a52010-10-05 11:24:23 +0000133 clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view));
cristy7eb1b7a2010-06-26 15:47:49 +0000134 if (clone_view == (WandView *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000135 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
cristy73b7d4c2010-06-27 00:31:00 +0000136 wand_view->name);
cristy3ed852e2009-09-05 21:47:34 +0000137 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
138 clone_view->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000139 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
cristy7eb1b7a2010-06-26 15:47:49 +0000140 WandViewId,(double) clone_view->id);
cristyc3ebda22010-06-27 17:11:57 +0000141 clone_view->description=ConstantString(wand_view->description);
cristy4c08aed2011-07-01 19:47:50 +0000142 clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
143 wand_view->exception);
cristyc3ebda22010-06-27 17:11:57 +0000144 clone_view->view=CloneCacheView(wand_view->view);
145 clone_view->extent=wand_view->extent;
146 clone_view->number_threads=wand_view->number_threads;
cristy3ed852e2009-09-05 21:47:34 +0000147 clone_view->exception=AcquireExceptionInfo();
cristy73b7d4c2010-06-27 00:31:00 +0000148 InheritException(clone_view->exception,wand_view->exception);
cristy73b7d4c2010-06-27 00:31:00 +0000149 for (i=0; i < (ssize_t) wand_view->number_threads; i++)
cristy3ed852e2009-09-05 21:47:34 +0000150 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
cristyc3ebda22010-06-27 17:11:57 +0000151 wand_view->pixel_wands[i],wand_view->extent.width);
cristy73b7d4c2010-06-27 00:31:00 +0000152 clone_view->debug=wand_view->debug;
cristy3ed852e2009-09-05 21:47:34 +0000153 if (clone_view->debug != MagickFalse)
154 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
155 clone_view->signature=WandSignature;
156 return(clone_view);
157}
158
159/*
160%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161% %
162% %
163% %
cristy7eb1b7a2010-06-26 15:47:49 +0000164% D e s t r o y W a n d V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000165% %
166% %
167% %
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169%
cristy73b7d4c2010-06-27 00:31:00 +0000170% DestroyWandView() deallocates memory associated with a wand view.
cristy3ed852e2009-09-05 21:47:34 +0000171%
cristy7eb1b7a2010-06-26 15:47:49 +0000172% The format of the DestroyWandView method is:
cristy3ed852e2009-09-05 21:47:34 +0000173%
cristy73b7d4c2010-06-27 00:31:00 +0000174% WandView *DestroyWandView(WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000175%
176% A description of each parameter follows:
177%
cristy73b7d4c2010-06-27 00:31:00 +0000178% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000179%
180*/
181
182static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
cristybb503372010-05-27 20:51:26 +0000183 const size_t number_wands,const size_t number_threads)
cristy3ed852e2009-09-05 21:47:34 +0000184{
cristybb503372010-05-27 20:51:26 +0000185 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000186 i;
187
188 assert(pixel_wands != (PixelWand ***) NULL);
cristybb503372010-05-27 20:51:26 +0000189 for (i=0; i < (ssize_t) number_threads; i++)
cristy3ed852e2009-09-05 21:47:34 +0000190 if (pixel_wands[i] != (PixelWand **) NULL)
191 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
cristyb41ee102010-10-04 16:46:15 +0000192 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
cristy3ed852e2009-09-05 21:47:34 +0000193 return(pixel_wands);
194}
195
cristy73b7d4c2010-06-27 00:31:00 +0000196WandExport WandView *DestroyWandView(WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000197{
cristy73b7d4c2010-06-27 00:31:00 +0000198 assert(wand_view != (WandView *) NULL);
199 assert(wand_view->signature == WandSignature);
200 wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
cristyc3ebda22010-06-27 17:11:57 +0000201 wand_view->extent.width,wand_view->number_threads);
cristy4c08aed2011-07-01 19:47:50 +0000202 wand_view->image=DestroyImage(wand_view->image);
cristy73b7d4c2010-06-27 00:31:00 +0000203 wand_view->view=DestroyCacheView(wand_view->view);
204 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
205 wand_view->signature=(~WandSignature);
206 RelinquishWandId(wand_view->id);
207 wand_view=(WandView *) RelinquishMagickMemory(wand_view);
208 return(wand_view);
cristy3ed852e2009-09-05 21:47:34 +0000209}
210
211/*
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213% %
214% %
215% %
cristy7eb1b7a2010-06-26 15:47:49 +0000216% D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +0000217% %
218% %
219% %
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221%
cristy73b7d4c2010-06-27 00:31:00 +0000222% DuplexTransferWandViewIterator() iterates over three wand views in
cristy3ed852e2009-09-05 21:47:34 +0000223% parallel and calls your transfer method for each scanline of the view. The
cristyc3ebda22010-06-27 17:11:57 +0000224% source and duplex pixel extent is not confined to the image canvas-- that is
cristy3ed852e2009-09-05 21:47:34 +0000225% you can include negative offsets or widths or heights that exceed the image
cristy73b7d4c2010-06-27 00:31:00 +0000226% dimension. However, the destination wand view is confined to the image
cristy3ed852e2009-09-05 21:47:34 +0000227% canvas-- that is no negative offsets or widths or heights that exceed the
228% image dimension are permitted.
229%
cristyd6dfc0d2010-06-27 19:30:49 +0000230% The callback signature is:
231%
232% MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
233% const WandView *duplex,WandView *destination,const ssize_t y,
234% const int thread_id,void *context)
235%
cristy58739472010-06-26 20:27:18 +0000236% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000237%
238% #pragma omp critical
239%
240% to define a section of code in your callback transfer method that must be
241% executed by a single thread at a time.
242%
cristy7eb1b7a2010-06-26 15:47:49 +0000243% The format of the DuplexTransferWandViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000244%
cristy7eb1b7a2010-06-26 15:47:49 +0000245% MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
246% WandView *duplex,WandView *destination,
247% DuplexTransferWandViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000248%
249% A description of each parameter follows:
250%
cristy73b7d4c2010-06-27 00:31:00 +0000251% o source: the source wand view.
cristy3ed852e2009-09-05 21:47:34 +0000252%
cristy73b7d4c2010-06-27 00:31:00 +0000253% o duplex: the duplex wand view.
cristy3ed852e2009-09-05 21:47:34 +0000254%
cristy73b7d4c2010-06-27 00:31:00 +0000255% o destination: the destination wand view.
cristy3ed852e2009-09-05 21:47:34 +0000256%
257% o transfer: the transfer callback method.
258%
259% o context: the user defined context.
260%
261*/
cristy58739472010-06-26 20:27:18 +0000262WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
263 WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
264 void *context)
cristy3ed852e2009-09-05 21:47:34 +0000265{
cristy3ed852e2009-09-05 21:47:34 +0000266 ExceptionInfo
267 *exception;
268
269 Image
270 *destination_image,
cristy3ed852e2009-09-05 21:47:34 +0000271 *source_image;
272
cristy3ed852e2009-09-05 21:47:34 +0000273 MagickBooleanType
274 status;
275
cristycee97112010-05-28 00:44:52 +0000276 MagickOffsetType
277 progress;
278
279 ssize_t
280 y;
281
cristy7eb1b7a2010-06-26 15:47:49 +0000282 assert(source != (WandView *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000283 assert(source->signature == WandSignature);
cristy7eb1b7a2010-06-26 15:47:49 +0000284 if (transfer == (DuplexTransferWandViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000285 return(MagickFalse);
286 source_image=source->wand->images;
cristy3ed852e2009-09-05 21:47:34 +0000287 destination_image=destination->wand->images;
cristy874276b2011-08-05 19:29:22 +0000288 exception=destination->exception;
cristy574cc262011-08-05 01:23:58 +0000289 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000290 return(MagickFalse);
291 status=MagickTrue;
292 progress=0;
cristyb5d5f722009-11-04 03:03:49 +0000293#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy09d81172010-10-21 16:15:05 +0000294 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
cristy3ed852e2009-09-05 21:47:34 +0000295#endif
cristyc3ebda22010-06-27 17:11:57 +0000296 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000297 {
cristy83e6d2a2010-09-17 17:35:13 +0000298 const int
299 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000300
cristy3ed852e2009-09-05 21:47:34 +0000301 MagickBooleanType
302 sync;
303
cristy4c08aed2011-07-01 19:47:50 +0000304 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +0000305 *restrict duplex_pixels,
306 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000307
cristybb503372010-05-27 20:51:26 +0000308 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000309 x;
310
cristy4c08aed2011-07-01 19:47:50 +0000311 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000312 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +0000313
314 if (status == MagickFalse)
315 continue;
cristyc3ebda22010-06-27 17:11:57 +0000316 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
317 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +0000318 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000319 {
320 status=MagickFalse;
321 continue;
322 }
cristyc3ebda22010-06-27 17:11:57 +0000323 for (x=0; x < (ssize_t) source->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000324 {
325 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +0000326 pixels+=GetPixelChannels(source->image);
cristy4c08aed2011-07-01 19:47:50 +0000327 }
cristyc3ebda22010-06-27 17:11:57 +0000328 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
329 duplex->extent.width,1,duplex->exception);
cristy4c08aed2011-07-01 19:47:50 +0000330 if (duplex_pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000331 {
332 status=MagickFalse;
333 continue;
334 }
cristyc3ebda22010-06-27 17:11:57 +0000335 for (x=0; x < (ssize_t) duplex->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000336 {
337 PixelSetQuantumPixel(duplex->image,duplex_pixels,
338 duplex->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +0000339 duplex_pixels+=GetPixelChannels(duplex->image);
cristy4c08aed2011-07-01 19:47:50 +0000340 }
cristy3ed852e2009-09-05 21:47:34 +0000341 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
cristyc3ebda22010-06-27 17:11:57 +0000342 destination->extent.x,y,destination->extent.width,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000343 if (destination_pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000344 {
345 status=MagickFalse;
346 continue;
347 }
cristyc3ebda22010-06-27 17:11:57 +0000348 for (x=0; x < (ssize_t) destination->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000349 {
350 PixelSetQuantumPixel(destination->image,destination_pixels,
351 destination->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +0000352 destination_pixels+=GetPixelChannels(destination->image);
cristy4c08aed2011-07-01 19:47:50 +0000353 }
cristyc3ebda22010-06-27 17:11:57 +0000354 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000355 status=MagickFalse;
cristy4c08aed2011-07-01 19:47:50 +0000356 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
357 destination->extent.x,y,destination->extent.width,1,exception);
cristyc3ebda22010-06-27 17:11:57 +0000358 for (x=0; x < (ssize_t) destination->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000359 {
360 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
361 destination_pixels);
cristyed231572011-07-14 02:18:59 +0000362 destination_pixels+=GetPixelChannels(destination->image);
cristy4c08aed2011-07-01 19:47:50 +0000363 }
cristy3ed852e2009-09-05 21:47:34 +0000364 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
365 if (sync == MagickFalse)
366 {
367 InheritException(destination->exception,GetCacheViewException(
368 source->view));
369 status=MagickFalse;
370 }
371 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
372 {
373 MagickBooleanType
374 proceed;
375
cristyb5d5f722009-11-04 03:03:49 +0000376#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000377 #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000378#endif
cristyc3ebda22010-06-27 17:11:57 +0000379 proceed=SetImageProgress(source_image,source->description,progress++,
380 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000381 if (proceed == MagickFalse)
382 status=MagickFalse;
383 }
384 }
385 return(status);
386}
387
388/*
389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390% %
391% %
392% %
cristy7eb1b7a2010-06-26 15:47:49 +0000393% G e t W a n d V i e w E x c e p t i o n %
cristy3ed852e2009-09-05 21:47:34 +0000394% %
395% %
396% %
397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398%
cristy7eb1b7a2010-06-26 15:47:49 +0000399% GetWandViewException() returns the severity, reason, and description of any
cristy73b7d4c2010-06-27 00:31:00 +0000400% error that occurs when utilizing a wand view.
cristy3ed852e2009-09-05 21:47:34 +0000401%
cristy7eb1b7a2010-06-26 15:47:49 +0000402% The format of the GetWandViewException method is:
cristy3ed852e2009-09-05 21:47:34 +0000403%
cristy73b7d4c2010-06-27 00:31:00 +0000404% char *GetWandViewException(const PixelWand *wand_view,
cristy3ed852e2009-09-05 21:47:34 +0000405% ExceptionType *severity)
406%
407% A description of each parameter follows:
408%
cristy73b7d4c2010-06-27 00:31:00 +0000409% o wand_view: the pixel wand_view.
cristy3ed852e2009-09-05 21:47:34 +0000410%
411% o severity: the severity of the error is returned here.
412%
413*/
cristy73b7d4c2010-06-27 00:31:00 +0000414WandExport char *GetWandViewException(const WandView *wand_view,
cristy3ed852e2009-09-05 21:47:34 +0000415 ExceptionType *severity)
416{
417 char
418 *description;
419
cristy73b7d4c2010-06-27 00:31:00 +0000420 assert(wand_view != (const WandView *) NULL);
421 assert(wand_view->signature == WandSignature);
422 if (wand_view->debug != MagickFalse)
423 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
cristy3ed852e2009-09-05 21:47:34 +0000424 assert(severity != (ExceptionType *) NULL);
cristy73b7d4c2010-06-27 00:31:00 +0000425 *severity=wand_view->exception->severity;
cristy3ed852e2009-09-05 21:47:34 +0000426 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
427 sizeof(*description));
428 if (description == (char *) NULL)
429 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
cristy73b7d4c2010-06-27 00:31:00 +0000430 wand_view->name);
cristy3ed852e2009-09-05 21:47:34 +0000431 *description='\0';
cristy73b7d4c2010-06-27 00:31:00 +0000432 if (wand_view->exception->reason != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000433 (void) CopyMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000434 wand_view->exception->severity,wand_view->exception->reason),
cristy3ed852e2009-09-05 21:47:34 +0000435 MaxTextExtent);
cristy73b7d4c2010-06-27 00:31:00 +0000436 if (wand_view->exception->description != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000437 {
438 (void) ConcatenateMagickString(description," (",MaxTextExtent);
439 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
cristy73b7d4c2010-06-27 00:31:00 +0000440 wand_view->exception->severity,wand_view->exception->description),
cristy3ed852e2009-09-05 21:47:34 +0000441 MaxTextExtent);
442 (void) ConcatenateMagickString(description,")",MaxTextExtent);
443 }
444 return(description);
445}
446
447/*
448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449% %
450% %
451% %
cristyc3ebda22010-06-27 17:11:57 +0000452% G e t W a n d V i e w E x t e n t %
cristy3ed852e2009-09-05 21:47:34 +0000453% %
454% %
455% %
456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457%
cristyc3ebda22010-06-27 17:11:57 +0000458% GetWandViewExtent() returns the wand view extent.
cristy3ed852e2009-09-05 21:47:34 +0000459%
cristyc3ebda22010-06-27 17:11:57 +0000460% The format of the GetWandViewExtent method is:
cristy3ed852e2009-09-05 21:47:34 +0000461%
cristyc3ebda22010-06-27 17:11:57 +0000462% RectangleInfo GetWandViewExtent(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000463%
464% A description of each parameter follows:
465%
cristy73b7d4c2010-06-27 00:31:00 +0000466% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000467%
468*/
cristyc3ebda22010-06-27 17:11:57 +0000469WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000470{
cristy73b7d4c2010-06-27 00:31:00 +0000471 assert(wand_view != (WandView *) NULL);
472 assert(wand_view->signature == WandSignature);
cristyc3ebda22010-06-27 17:11:57 +0000473 return(wand_view->extent);
cristy3ed852e2009-09-05 21:47:34 +0000474}
475
476/*
477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478% %
479% %
480% %
cristy7eb1b7a2010-06-26 15:47:49 +0000481% G e t W a n d V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +0000482% %
483% %
484% %
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486%
cristy73b7d4c2010-06-27 00:31:00 +0000487% GetWandViewIterator() iterates over the wand view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +0000488% your get method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +0000489% not confined to the image canvas-- that is you can include negative offsets
490% or widths or heights that exceed the image dimension. Any updates to
491% the pixels in your callback are ignored.
492%
cristyd6dfc0d2010-06-27 19:30:49 +0000493% The callback signature is:
494%
495% MagickBooleanType GetImageViewMethod(const WandView *source,
496% const ssize_t y,const int thread_id,void *context)
497%
cristy58739472010-06-26 20:27:18 +0000498% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000499%
500% #pragma omp critical
501%
502% to define a section of code in your callback get method that must be
503% executed by a single thread at a time.
504%
cristy7eb1b7a2010-06-26 15:47:49 +0000505% The format of the GetWandViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000506%
cristy7eb1b7a2010-06-26 15:47:49 +0000507% MagickBooleanType GetWandViewIterator(WandView *source,
508% GetWandViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000509%
510% A description of each parameter follows:
511%
cristy73b7d4c2010-06-27 00:31:00 +0000512% o source: the source wand view.
cristy3ed852e2009-09-05 21:47:34 +0000513%
514% o get: the get callback method.
515%
516% o context: the user defined context.
517%
518*/
cristy7eb1b7a2010-06-26 15:47:49 +0000519WandExport MagickBooleanType GetWandViewIterator(WandView *source,
520 GetWandViewMethod get,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000521{
cristy3ed852e2009-09-05 21:47:34 +0000522 Image
523 *source_image;
524
cristy3ed852e2009-09-05 21:47:34 +0000525 MagickBooleanType
526 status;
527
cristycee97112010-05-28 00:44:52 +0000528 MagickOffsetType
529 progress;
530
531 ssize_t
532 y;
533
cristy7eb1b7a2010-06-26 15:47:49 +0000534 assert(source != (WandView *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000535 assert(source->signature == WandSignature);
cristy7eb1b7a2010-06-26 15:47:49 +0000536 if (get == (GetWandViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000537 return(MagickFalse);
538 source_image=source->wand->images;
539 status=MagickTrue;
540 progress=0;
cristyb5d5f722009-11-04 03:03:49 +0000541#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy09d81172010-10-21 16:15:05 +0000542 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
cristy3ed852e2009-09-05 21:47:34 +0000543#endif
cristyc3ebda22010-06-27 17:11:57 +0000544 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000545 {
cristy83e6d2a2010-09-17 17:35:13 +0000546 const int
547 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000548
cristy4c08aed2011-07-01 19:47:50 +0000549 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000550 *pixels;
551
cristybb503372010-05-27 20:51:26 +0000552 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000553 x;
554
555 if (status == MagickFalse)
556 continue;
cristyc3ebda22010-06-27 17:11:57 +0000557 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
558 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +0000559 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000560 {
561 status=MagickFalse;
562 continue;
563 }
cristyc3ebda22010-06-27 17:11:57 +0000564 for (x=0; x < (ssize_t) source->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000565 {
566 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +0000567 pixels+=GetPixelChannels(source->image);
cristy4c08aed2011-07-01 19:47:50 +0000568 }
cristyd6dfc0d2010-06-27 19:30:49 +0000569 if (get(source,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000570 status=MagickFalse;
571 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
572 {
573 MagickBooleanType
574 proceed;
575
cristyb5d5f722009-11-04 03:03:49 +0000576#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000577 #pragma omp critical (MagickWand_GetWandViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000578#endif
cristyc3ebda22010-06-27 17:11:57 +0000579 proceed=SetImageProgress(source_image,source->description,progress++,
580 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000581 if (proceed == MagickFalse)
582 status=MagickFalse;
583 }
584 }
585 return(status);
586}
587
588/*
589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590% %
591% %
592% %
cristy7eb1b7a2010-06-26 15:47:49 +0000593% G e t W a n d V i e w P i x e l s %
cristy3ed852e2009-09-05 21:47:34 +0000594% %
595% %
596% %
597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598%
cristy73b7d4c2010-06-27 00:31:00 +0000599% GetWandViewPixels() returns the wand view pixel_wands.
cristy3ed852e2009-09-05 21:47:34 +0000600%
cristy7eb1b7a2010-06-26 15:47:49 +0000601% The format of the GetWandViewPixels method is:
cristy3ed852e2009-09-05 21:47:34 +0000602%
cristy73b7d4c2010-06-27 00:31:00 +0000603% PixelWand *GetWandViewPixels(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000604%
605% A description of each parameter follows:
606%
cristy73b7d4c2010-06-27 00:31:00 +0000607% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000608%
609*/
cristy73b7d4c2010-06-27 00:31:00 +0000610WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000611{
cristy83e6d2a2010-09-17 17:35:13 +0000612 const int
613 id = GetOpenMPThreadId();
cristy3ed852e2009-09-05 21:47:34 +0000614
cristy73b7d4c2010-06-27 00:31:00 +0000615 assert(wand_view != (WandView *) NULL);
616 assert(wand_view->signature == WandSignature);
cristy73b7d4c2010-06-27 00:31:00 +0000617 return(wand_view->pixel_wands[id]);
cristy3ed852e2009-09-05 21:47:34 +0000618}
619
620/*
621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622% %
623% %
624% %
cristy7eb1b7a2010-06-26 15:47:49 +0000625% G e t W a n d V i e w W a n d %
cristy3ed852e2009-09-05 21:47:34 +0000626% %
627% %
628% %
629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630%
cristy73b7d4c2010-06-27 00:31:00 +0000631% GetWandViewWand() returns the magick wand associated with the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000632%
cristy7eb1b7a2010-06-26 15:47:49 +0000633% The format of the GetWandViewWand method is:
cristy3ed852e2009-09-05 21:47:34 +0000634%
cristy73b7d4c2010-06-27 00:31:00 +0000635% MagickWand *GetWandViewWand(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000636%
637% A description of each parameter follows:
638%
cristy73b7d4c2010-06-27 00:31:00 +0000639% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000640%
641*/
cristy73b7d4c2010-06-27 00:31:00 +0000642WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000643{
cristy73b7d4c2010-06-27 00:31:00 +0000644 assert(wand_view != (WandView *) NULL);
645 assert(wand_view->signature == WandSignature);
646 return(wand_view->wand);
cristy3ed852e2009-09-05 21:47:34 +0000647}
648
649/*
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651% %
652% %
653% %
cristy7eb1b7a2010-06-26 15:47:49 +0000654% I s W a n d V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000655% %
656% %
657% %
658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659%
cristy73b7d4c2010-06-27 00:31:00 +0000660% IsWandView() returns MagickTrue if the the parameter is verified as a wand
661% view object.
cristy3ed852e2009-09-05 21:47:34 +0000662%
cristy7eb1b7a2010-06-26 15:47:49 +0000663% The format of the IsWandView method is:
cristy3ed852e2009-09-05 21:47:34 +0000664%
cristy73b7d4c2010-06-27 00:31:00 +0000665% MagickBooleanType IsWandView(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000666%
667% A description of each parameter follows:
668%
cristy73b7d4c2010-06-27 00:31:00 +0000669% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000670%
671*/
cristy73b7d4c2010-06-27 00:31:00 +0000672WandExport MagickBooleanType IsWandView(const WandView *wand_view)
cristy3ed852e2009-09-05 21:47:34 +0000673{
674 size_t
675 length;
676
cristy73b7d4c2010-06-27 00:31:00 +0000677 if (wand_view == (const WandView *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000678 return(MagickFalse);
cristy73b7d4c2010-06-27 00:31:00 +0000679 if (wand_view->signature != WandSignature)
cristy3ed852e2009-09-05 21:47:34 +0000680 return(MagickFalse);
cristy7eb1b7a2010-06-26 15:47:49 +0000681 length=strlen(WandViewId);
cristy73b7d4c2010-06-27 00:31:00 +0000682 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
cristy3ed852e2009-09-05 21:47:34 +0000683 return(MagickFalse);
684 return(MagickTrue);
685}
686
687/*
688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689% %
690% %
691% %
cristy7eb1b7a2010-06-26 15:47:49 +0000692% N e w W a n d V i e w %
cristy3ed852e2009-09-05 21:47:34 +0000693% %
694% %
695% %
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697%
cristy73b7d4c2010-06-27 00:31:00 +0000698% NewWandView() returns a wand view required for all other methods in the
699% Wand View API.
cristy3ed852e2009-09-05 21:47:34 +0000700%
cristy7eb1b7a2010-06-26 15:47:49 +0000701% The format of the NewWandView method is:
cristy3ed852e2009-09-05 21:47:34 +0000702%
cristy7eb1b7a2010-06-26 15:47:49 +0000703% WandView *NewWandView(MagickWand *wand)
cristy3ed852e2009-09-05 21:47:34 +0000704%
705% A description of each parameter follows:
706%
707% o wand: the wand.
708%
709*/
710
cristybb503372010-05-27 20:51:26 +0000711static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands,
712 const size_t number_threads)
cristy3ed852e2009-09-05 21:47:34 +0000713{
714 PixelWand
715 ***pixel_wands;
716
cristybb503372010-05-27 20:51:26 +0000717 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000718 i;
719
cristyb41ee102010-10-04 16:46:15 +0000720 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
cristy3ed852e2009-09-05 21:47:34 +0000721 sizeof(*pixel_wands));
722 if (pixel_wands == (PixelWand ***) NULL)
723 return((PixelWand ***) NULL);
724 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
cristybb503372010-05-27 20:51:26 +0000725 for (i=0; i < (ssize_t) number_threads; i++)
cristy3ed852e2009-09-05 21:47:34 +0000726 {
727 pixel_wands[i]=NewPixelWands(number_wands);
728 if (pixel_wands[i] == (PixelWand **) NULL)
729 return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
730 }
731 return(pixel_wands);
732}
733
cristy7eb1b7a2010-06-26 15:47:49 +0000734WandExport WandView *NewWandView(MagickWand *wand)
cristy3ed852e2009-09-05 21:47:34 +0000735{
cristy7eb1b7a2010-06-26 15:47:49 +0000736 WandView
cristy73b7d4c2010-06-27 00:31:00 +0000737 *wand_view;
cristy3ed852e2009-09-05 21:47:34 +0000738
739 assert(wand != (MagickWand *) NULL);
cristyc3ebda22010-06-27 17:11:57 +0000740 assert(wand->signature == WandSignature);
cristy73bd4a52010-10-05 11:24:23 +0000741 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
cristy73b7d4c2010-06-27 00:31:00 +0000742 if (wand_view == (WandView *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000743 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
744 GetExceptionMessage(errno));
cristy73b7d4c2010-06-27 00:31:00 +0000745 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
746 wand_view->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000747 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
cristy73b7d4c2010-06-27 00:31:00 +0000748 WandViewId,(double) wand_view->id);
cristyc3ebda22010-06-27 17:11:57 +0000749 wand_view->description=ConstantString("WandView");
cristy73b7d4c2010-06-27 00:31:00 +0000750 wand_view->wand=wand;
751 wand_view->view=AcquireCacheView(wand_view->wand->images);
cristyc3ebda22010-06-27 17:11:57 +0000752 wand_view->extent.width=wand->images->columns;
753 wand_view->extent.height=wand->images->rows;
cristy73b7d4c2010-06-27 00:31:00 +0000754 wand_view->number_threads=GetOpenMPMaximumThreads();
cristyc3ebda22010-06-27 17:11:57 +0000755 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
756 wand_view->number_threads);
757 wand_view->exception=AcquireExceptionInfo();
758 if (wand_view->pixel_wands == (PixelWand ***) NULL)
759 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
760 GetExceptionMessage(errno));
761 wand_view->debug=IsEventLogging();
762 wand_view->signature=WandSignature;
763 return(wand_view);
764}
765
766/*
767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768% %
769% %
770% %
771% N e w W a n d V i e w E x t e n t %
772% %
773% %
774% %
775%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776%
777% NewWandViewExtent() returns a wand view required for all other methods
778% in the Wand View API.
779%
780% The format of the NewWandViewExtent method is:
781%
782% WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
783% const ssize_t y,const size_t width,const size_t height)
784%
785% A description of each parameter follows:
786%
787% o wand: the magick wand.
788%
789% o x,y,columns,rows: These values define the perimeter of a extent of
790% pixel_wands view.
791%
792*/
793WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
794 const ssize_t y,const size_t width,const size_t height)
795{
796 WandView
797 *wand_view;
798
799 assert(wand != (MagickWand *) NULL);
800 assert(wand->signature == WandSignature);
cristy73bd4a52010-10-05 11:24:23 +0000801 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
cristyc3ebda22010-06-27 17:11:57 +0000802 if (wand_view == (WandView *) NULL)
803 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
804 GetExceptionMessage(errno));
805 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
806 wand_view->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000807 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
cristyc3ebda22010-06-27 17:11:57 +0000808 WandViewId,(double) wand_view->id);
809 wand_view->description=ConstantString("WandView");
810 wand_view->view=AcquireCacheView(wand_view->wand->images);
811 wand_view->wand=wand;
812 wand_view->extent.width=width;
813 wand_view->extent.height=height;
814 wand_view->extent.x=x;
815 wand_view->extent.y=y;
816 wand_view->number_threads=GetOpenMPMaximumThreads();
817 wand_view->exception=AcquireExceptionInfo();
818 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
cristy73b7d4c2010-06-27 00:31:00 +0000819 wand_view->number_threads);
820 if (wand_view->pixel_wands == (PixelWand ***) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000821 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
822 GetExceptionMessage(errno));
cristy73b7d4c2010-06-27 00:31:00 +0000823 wand_view->debug=IsEventLogging();
824 wand_view->signature=WandSignature;
825 return(wand_view);
cristy3ed852e2009-09-05 21:47:34 +0000826}
827
828/*
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830% %
831% %
832% %
cristyc3ebda22010-06-27 17:11:57 +0000833% S e t W a n d V i e w D e s c r i p t i o n %
cristy3ed852e2009-09-05 21:47:34 +0000834% %
835% %
836% %
837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838%
cristyc3ebda22010-06-27 17:11:57 +0000839% SetWandViewDescription() associates a description with an image view.
cristy3ed852e2009-09-05 21:47:34 +0000840%
cristyc3ebda22010-06-27 17:11:57 +0000841% The format of the SetWandViewDescription method is:
cristy3ed852e2009-09-05 21:47:34 +0000842%
cristyc3ebda22010-06-27 17:11:57 +0000843% void SetWandViewDescription(WandView *image_view,const char *description)
cristy3ed852e2009-09-05 21:47:34 +0000844%
845% A description of each parameter follows:
846%
cristyc3ebda22010-06-27 17:11:57 +0000847% o wand_view: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000848%
cristyc3ebda22010-06-27 17:11:57 +0000849% o description: the wand view description.
cristy3ed852e2009-09-05 21:47:34 +0000850%
851*/
cristyc3ebda22010-06-27 17:11:57 +0000852MagickExport void SetWandViewDescription(WandView *wand_view,
853 const char *description)
cristy3ed852e2009-09-05 21:47:34 +0000854{
cristyc3ebda22010-06-27 17:11:57 +0000855 assert(wand_view != (WandView *) NULL);
856 assert(wand_view->signature == WandSignature);
857 wand_view->description=ConstantString(description);
cristy3ed852e2009-09-05 21:47:34 +0000858}
859
860/*
861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862% %
863% %
864% %
cristy7eb1b7a2010-06-26 15:47:49 +0000865% S e t W a n d V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +0000866% %
867% %
868% %
869%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870%
cristy73b7d4c2010-06-27 00:31:00 +0000871% SetWandViewIterator() iterates over the wand view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +0000872% your set method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +0000873% confined to the image canvas-- that is no negative offsets or widths or
874% heights that exceed the image dimension. The pixels are initiallly
875% undefined and any settings you make in the callback method are automagically
876% synced back to your image.
877%
cristyd6dfc0d2010-06-27 19:30:49 +0000878% The callback signature is:
879%
880% MagickBooleanType SetImageViewMethod(ImageView *destination,
881% const ssize_t y,const int thread_id,void *context)
882%
cristy58739472010-06-26 20:27:18 +0000883% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +0000884%
885% #pragma omp critical
886%
887% to define a section of code in your callback set method that must be
888% executed by a single thread at a time.
889%
cristy7eb1b7a2010-06-26 15:47:49 +0000890% The format of the SetWandViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +0000891%
cristy7eb1b7a2010-06-26 15:47:49 +0000892% MagickBooleanType SetWandViewIterator(WandView *destination,
893% SetWandViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000894%
895% A description of each parameter follows:
896%
cristy73b7d4c2010-06-27 00:31:00 +0000897% o destination: the wand view.
cristy3ed852e2009-09-05 21:47:34 +0000898%
899% o set: the set callback method.
900%
901% o context: the user defined context.
902%
903*/
cristy7eb1b7a2010-06-26 15:47:49 +0000904WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
905 SetWandViewMethod set,void *context)
cristy3ed852e2009-09-05 21:47:34 +0000906{
cristy3ed852e2009-09-05 21:47:34 +0000907 ExceptionInfo
908 *exception;
909
910 Image
911 *destination_image;
912
cristy3ed852e2009-09-05 21:47:34 +0000913 MagickBooleanType
914 status;
915
cristycee97112010-05-28 00:44:52 +0000916 MagickOffsetType
917 progress;
918
919 ssize_t
920 y;
921
cristy7eb1b7a2010-06-26 15:47:49 +0000922 assert(destination != (WandView *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000923 assert(destination->signature == WandSignature);
cristy7eb1b7a2010-06-26 15:47:49 +0000924 if (set == (SetWandViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000925 return(MagickFalse);
926 destination_image=destination->wand->images;
cristy874276b2011-08-05 19:29:22 +0000927 exception=destination->exception;
cristy574cc262011-08-05 01:23:58 +0000928 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000929 return(MagickFalse);
930 status=MagickTrue;
931 progress=0;
cristyb5d5f722009-11-04 03:03:49 +0000932#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy09d81172010-10-21 16:15:05 +0000933 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(destination->number_threads)
cristy3ed852e2009-09-05 21:47:34 +0000934#endif
cristyc3ebda22010-06-27 17:11:57 +0000935 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000936 {
cristy83e6d2a2010-09-17 17:35:13 +0000937 const int
938 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +0000939
cristy3ed852e2009-09-05 21:47:34 +0000940 MagickBooleanType
941 sync;
942
cristybb503372010-05-27 20:51:26 +0000943 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000944 x;
945
cristy4c08aed2011-07-01 19:47:50 +0000946 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000947 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000948
949 if (status == MagickFalse)
950 continue;
cristyc3ebda22010-06-27 17:11:57 +0000951 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
952 y,destination->extent.width,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000953 if (pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000954 {
955 InheritException(destination->exception,GetCacheViewException(
956 destination->view));
957 status=MagickFalse;
958 continue;
959 }
cristyd6dfc0d2010-06-27 19:30:49 +0000960 if (set(destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000961 status=MagickFalse;
cristyc3ebda22010-06-27 17:11:57 +0000962 for (x=0; x < (ssize_t) destination->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000963 {
964 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
965 pixels);
cristyed231572011-07-14 02:18:59 +0000966 pixels+=GetPixelChannels(destination->image);
cristy4c08aed2011-07-01 19:47:50 +0000967 }
cristy3ed852e2009-09-05 21:47:34 +0000968 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
969 if (sync == MagickFalse)
970 {
971 InheritException(destination->exception,GetCacheViewException(
972 destination->view));
973 status=MagickFalse;
974 }
975 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
976 {
977 MagickBooleanType
978 proceed;
979
cristyb5d5f722009-11-04 03:03:49 +0000980#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +0000981 #pragma omp critical (MagickWand_SetWandViewIterator)
cristy3ed852e2009-09-05 21:47:34 +0000982#endif
cristyc3ebda22010-06-27 17:11:57 +0000983 proceed=SetImageProgress(destination_image,destination->description,
984 progress++,destination->extent.height);
cristy3ed852e2009-09-05 21:47:34 +0000985 if (proceed == MagickFalse)
986 status=MagickFalse;
987 }
988 }
989 return(status);
990}
991
992/*
993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994% %
995% %
996% %
cristy09d81172010-10-21 16:15:05 +0000997% S e t W a n d V i e w T h r e a d s %
998% %
999% %
1000% %
1001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002%
1003% SetWandViewThreads() sets the number of threads in a thread team.
1004%
1005% The format of the SetWandViewDescription method is:
1006%
1007% void SetWandViewThreads(WandView *image_view,
1008% const size_t number_threads)
1009%
1010% A description of each parameter follows:
1011%
1012% o image_view: the image view.
1013%
1014% o number_threads: the number of threads in a thread team.
1015%
1016*/
1017MagickExport void SetWandViewThreads(WandView *image_view,
1018 const size_t number_threads)
1019{
1020 assert(image_view != (WandView *) NULL);
1021 assert(image_view->signature == MagickSignature);
1022 image_view->number_threads=number_threads;
1023 if (number_threads > GetOpenMPMaximumThreads())
1024 image_view->number_threads=GetOpenMPMaximumThreads();
1025}
1026
1027/*
1028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029% %
1030% %
1031% %
cristy7eb1b7a2010-06-26 15:47:49 +00001032% T r a n s f e r W a n d V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +00001033% %
1034% %
1035% %
1036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037%
cristy73b7d4c2010-06-27 00:31:00 +00001038% TransferWandViewIterator() iterates over two wand views in parallel and
cristy3ed852e2009-09-05 21:47:34 +00001039% calls your transfer method for each scanline of the view. The source pixel
cristyc3ebda22010-06-27 17:11:57 +00001040% extent is not confined to the image canvas-- that is you can include
cristy3ed852e2009-09-05 21:47:34 +00001041% negative offsets or widths or heights that exceed the image dimension.
cristy73b7d4c2010-06-27 00:31:00 +00001042% However, the destination wand view is confined to the image canvas-- that
cristy3ed852e2009-09-05 21:47:34 +00001043% is no negative offsets or widths or heights that exceed the image dimension
1044% are permitted.
1045%
cristyd6dfc0d2010-06-27 19:30:49 +00001046% The callback signature is:
1047%
1048% MagickBooleanType TransferImageViewMethod(const WandView *source,
1049% WandView *destination,const ssize_t y,const int thread_id,
1050% void *context)
1051%
cristy58739472010-06-26 20:27:18 +00001052% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +00001053%
1054% #pragma omp critical
1055%
1056% to define a section of code in your callback transfer method that must be
1057% executed by a single thread at a time.
1058%
cristy7eb1b7a2010-06-26 15:47:49 +00001059% The format of the TransferWandViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +00001060%
cristy7eb1b7a2010-06-26 15:47:49 +00001061% MagickBooleanType TransferWandViewIterator(WandView *source,
1062% WandView *destination,TransferWandViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001063%
1064% A description of each parameter follows:
1065%
cristy73b7d4c2010-06-27 00:31:00 +00001066% o source: the source wand view.
cristy3ed852e2009-09-05 21:47:34 +00001067%
cristy73b7d4c2010-06-27 00:31:00 +00001068% o destination: the destination wand view.
cristy3ed852e2009-09-05 21:47:34 +00001069%
1070% o transfer: the transfer callback method.
1071%
1072% o context: the user defined context.
1073%
1074*/
cristy7eb1b7a2010-06-26 15:47:49 +00001075WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1076 WandView *destination,TransferWandViewMethod transfer,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001077{
cristy3ed852e2009-09-05 21:47:34 +00001078 ExceptionInfo
1079 *exception;
1080
1081 Image
1082 *destination_image,
1083 *source_image;
1084
cristy3ed852e2009-09-05 21:47:34 +00001085 MagickBooleanType
1086 status;
1087
cristycee97112010-05-28 00:44:52 +00001088 MagickOffsetType
1089 progress;
1090
1091 ssize_t
1092 y;
1093
cristy7eb1b7a2010-06-26 15:47:49 +00001094 assert(source != (WandView *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001095 assert(source->signature == WandSignature);
cristy7eb1b7a2010-06-26 15:47:49 +00001096 if (transfer == (TransferWandViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001097 return(MagickFalse);
1098 source_image=source->wand->images;
1099 destination_image=destination->wand->images;
cristy874276b2011-08-05 19:29:22 +00001100 exception=destination->exception;
cristy574cc262011-08-05 01:23:58 +00001101 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001102 return(MagickFalse);
1103 status=MagickTrue;
1104 progress=0;
cristyb5d5f722009-11-04 03:03:49 +00001105#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy09d81172010-10-21 16:15:05 +00001106 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
cristy3ed852e2009-09-05 21:47:34 +00001107#endif
cristyc3ebda22010-06-27 17:11:57 +00001108 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001109 {
cristy83e6d2a2010-09-17 17:35:13 +00001110 const int
1111 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +00001112
cristy3ed852e2009-09-05 21:47:34 +00001113 MagickBooleanType
1114 sync;
1115
cristy4c08aed2011-07-01 19:47:50 +00001116 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001117 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001118
cristybb503372010-05-27 20:51:26 +00001119 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001120 x;
1121
cristy4c08aed2011-07-01 19:47:50 +00001122 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001123 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +00001124
1125 if (status == MagickFalse)
1126 continue;
cristyc3ebda22010-06-27 17:11:57 +00001127 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1128 source->extent.width,1,source->exception);
cristy4c08aed2011-07-01 19:47:50 +00001129 if (pixels == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001130 {
1131 status=MagickFalse;
1132 continue;
1133 }
cristyc3ebda22010-06-27 17:11:57 +00001134 for (x=0; x < (ssize_t) source->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +00001135 {
1136 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +00001137 pixels+=GetPixelChannels(source->image);
cristy4c08aed2011-07-01 19:47:50 +00001138 }
cristy3ed852e2009-09-05 21:47:34 +00001139 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
cristyc3ebda22010-06-27 17:11:57 +00001140 destination->extent.x,y,destination->extent.width,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001141 if (destination_pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001142 {
1143 status=MagickFalse;
1144 continue;
1145 }
cristyc3ebda22010-06-27 17:11:57 +00001146 for (x=0; x < (ssize_t) destination->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +00001147 {
1148 PixelSetQuantumPixel(destination->image,destination_pixels,
1149 destination->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +00001150 destination_pixels+=GetPixelChannels(destination->image);
cristy4c08aed2011-07-01 19:47:50 +00001151 }
cristyc3ebda22010-06-27 17:11:57 +00001152 if (transfer(source,destination,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001153 status=MagickFalse;
cristy4c08aed2011-07-01 19:47:50 +00001154 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1155 destination->extent.x,y,destination->extent.width,1,exception);
cristyc3ebda22010-06-27 17:11:57 +00001156 for (x=0; x < (ssize_t) destination->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +00001157 {
1158 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1159 destination_pixels);
cristyed231572011-07-14 02:18:59 +00001160 destination_pixels+=GetPixelChannels(destination->image);
cristy4c08aed2011-07-01 19:47:50 +00001161 }
cristy3ed852e2009-09-05 21:47:34 +00001162 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1163 if (sync == MagickFalse)
1164 {
1165 InheritException(destination->exception,GetCacheViewException(
1166 source->view));
1167 status=MagickFalse;
1168 }
1169 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1170 {
1171 MagickBooleanType
1172 proceed;
1173
cristyb5d5f722009-11-04 03:03:49 +00001174#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +00001175 #pragma omp critical (MagickWand_TransferWandViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001176#endif
cristyc3ebda22010-06-27 17:11:57 +00001177 proceed=SetImageProgress(source_image,source->description,progress++,
1178 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +00001179 if (proceed == MagickFalse)
1180 status=MagickFalse;
1181 }
1182 }
1183 return(status);
1184}
1185
1186/*
1187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188% %
1189% %
1190% %
cristy7eb1b7a2010-06-26 15:47:49 +00001191% U p d a t e W a n d V i e w I t e r a t o r %
cristy3ed852e2009-09-05 21:47:34 +00001192% %
1193% %
1194% %
1195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196%
cristy73b7d4c2010-06-27 00:31:00 +00001197% UpdateWandViewIterator() iterates over the wand view in parallel and calls
cristyc3ebda22010-06-27 17:11:57 +00001198% your update method for each scanline of the view. The pixel extent is
cristy3ed852e2009-09-05 21:47:34 +00001199% confined to the image canvas-- that is no negative offsets or widths or
1200% heights that exceed the image dimension are permitted. Updates to pixels
1201% in your callback are automagically synced back to the image.
1202%
cristyd6dfc0d2010-06-27 19:30:49 +00001203% The callback signature is:
1204%
1205% MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1206% const int thread_id,void *context)
1207%
cristy58739472010-06-26 20:27:18 +00001208% Use this pragma if the view is not single threaded:
cristy3ed852e2009-09-05 21:47:34 +00001209%
1210% #pragma omp critical
1211%
1212% to define a section of code in your callback update method that must be
1213% executed by a single thread at a time.
1214%
cristy7eb1b7a2010-06-26 15:47:49 +00001215% The format of the UpdateWandViewIterator method is:
cristy3ed852e2009-09-05 21:47:34 +00001216%
cristy7eb1b7a2010-06-26 15:47:49 +00001217% MagickBooleanType UpdateWandViewIterator(WandView *source,
1218% UpdateWandViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001219%
1220% A description of each parameter follows:
1221%
cristy73b7d4c2010-06-27 00:31:00 +00001222% o source: the source wand view.
cristy3ed852e2009-09-05 21:47:34 +00001223%
1224% o update: the update callback method.
1225%
1226% o context: the user defined context.
1227%
1228*/
cristy7eb1b7a2010-06-26 15:47:49 +00001229WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1230 UpdateWandViewMethod update,void *context)
cristy3ed852e2009-09-05 21:47:34 +00001231{
cristy3ed852e2009-09-05 21:47:34 +00001232 ExceptionInfo
1233 *exception;
1234
1235 Image
1236 *source_image;
1237
cristy3ed852e2009-09-05 21:47:34 +00001238 MagickBooleanType
1239 status;
1240
cristycee97112010-05-28 00:44:52 +00001241 MagickOffsetType
1242 progress;
1243
1244 ssize_t
1245 y;
1246
cristy7eb1b7a2010-06-26 15:47:49 +00001247 assert(source != (WandView *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001248 assert(source->signature == WandSignature);
cristy7eb1b7a2010-06-26 15:47:49 +00001249 if (update == (UpdateWandViewMethod) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001250 return(MagickFalse);
1251 source_image=source->wand->images;
cristy874276b2011-08-05 19:29:22 +00001252 exception=source->exception;
cristy574cc262011-08-05 01:23:58 +00001253 if (SetImageStorageClass(source_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001254 return(MagickFalse);
1255 status=MagickTrue;
1256 progress=0;
cristyb5d5f722009-11-04 03:03:49 +00001257#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy09d81172010-10-21 16:15:05 +00001258 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
cristy3ed852e2009-09-05 21:47:34 +00001259#endif
cristyc3ebda22010-06-27 17:11:57 +00001260 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
cristy3ed852e2009-09-05 21:47:34 +00001261 {
cristy83e6d2a2010-09-17 17:35:13 +00001262 const int
1263 id = GetOpenMPThreadId();
cristyad740052010-07-03 01:38:03 +00001264
cristybb503372010-05-27 20:51:26 +00001265 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001266 x;
1267
cristy4c08aed2011-07-01 19:47:50 +00001268 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001269 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001270
1271 if (status == MagickFalse)
1272 continue;
cristyc3ebda22010-06-27 17:11:57 +00001273 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1274 source->extent.width,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001275 if (pixels == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001276 {
1277 InheritException(source->exception,GetCacheViewException(
1278 source->view));
1279 status=MagickFalse;
1280 continue;
1281 }
cristyc3ebda22010-06-27 17:11:57 +00001282 for (x=0; x < (ssize_t) source->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +00001283 {
1284 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
cristyed231572011-07-14 02:18:59 +00001285 pixels+=GetPixelChannels(source->image);
cristy4c08aed2011-07-01 19:47:50 +00001286 }
cristyc3ebda22010-06-27 17:11:57 +00001287 if (update(source,y,id,context) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001288 status=MagickFalse;
cristyc3ebda22010-06-27 17:11:57 +00001289 for (x=0; x < (ssize_t) source->extent.width; x++)
cristy4c08aed2011-07-01 19:47:50 +00001290 {
1291 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
cristyed231572011-07-14 02:18:59 +00001292 pixels+=GetPixelChannels(source->image);
cristy4c08aed2011-07-01 19:47:50 +00001293 }
cristy3ed852e2009-09-05 21:47:34 +00001294 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1295 {
1296 InheritException(source->exception,GetCacheViewException(source->view));
1297 status=MagickFalse;
1298 }
1299 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1300 {
1301 MagickBooleanType
1302 proceed;
1303
cristyb5d5f722009-11-04 03:03:49 +00001304#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy7eb1b7a2010-06-26 15:47:49 +00001305 #pragma omp critical (MagickWand_UpdateWandViewIterator)
cristy3ed852e2009-09-05 21:47:34 +00001306#endif
cristyc3ebda22010-06-27 17:11:57 +00001307 proceed=SetImageProgress(source_image,source->description,progress++,
1308 source->extent.height);
cristy3ed852e2009-09-05 21:47:34 +00001309 if (proceed == MagickFalse)
1310 status=MagickFalse;
1311 }
1312 }
1313 return(status);
1314}