blob: ad7801497ef3b26b1675ba5bed37d7da4f5287ef [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP IIIII X X EEEEE L %
7% P P I X X E L %
8% PPPP I X EEE L %
9% P I X X E L %
10% P IIIII X X EEEEE LLLLL %
11% %
12% IIIII TTTTT EEEEE RRRR AAA TTTTT OOO RRRR %
13% I T E R R A A T O O R R %
14% I T EEE RRRR AAAAA T O O RRRR %
15% I T E R R A A T O O R R %
16% IIIII T EEEEE R R A A T OOO R R %
17% %
18% %
19% ImageMagick Image Pixel Iterator Methods %
20% %
21% Software Design %
cristyde984cd2013-12-01 14:49:27 +000022% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000023% March 2003 %
24% %
25% %
Cristy7ce65e72015-12-12 18:03:16 -050026% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000027% dedicated to making software imaging solutions freely available. %
28% %
29% You may not use this file except in compliance with the License. You may %
30% obtain a copy of the License at %
31% %
32% http://www.imagemagick.org/script/license.php %
33% %
34% Unless required by applicable law or agreed to in writing, software %
35% distributed under the License is distributed on an "AS IS" BASIS, %
36% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
37% See the License for the specific language governing permissions and %
38% limitations under the License. %
39% %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42%
43%
44*/
45
46/*
47 Include declarations.
48*/
cristy4c08aed2011-07-01 19:47:50 +000049#include "MagickWand/studio.h"
50#include "MagickWand/MagickWand.h"
51#include "MagickWand/magick-wand-private.h"
52#include "MagickWand/pixel-iterator.h"
53#include "MagickWand/pixel-wand.h"
54#include "MagickWand/wand.h"
cristy3ed852e2009-09-05 21:47:34 +000055
56/*
57 Define declarations.
58*/
59#define PixelIteratorId "PixelIterator"
60
61/*
62 Typedef declarations.
63*/
64struct _PixelIterator
65{
cristybb503372010-05-27 20:51:26 +000066 size_t
cristy3ed852e2009-09-05 21:47:34 +000067 id;
68
69 char
cristy151b66d2015-04-15 10:50:31 +000070 name[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +000071
72 ExceptionInfo
73 *exception;
74
75 CacheView
76 *view;
77
78 RectangleInfo
79 region;
80
81 MagickBooleanType
anthonya89dd172011-10-04 13:29:35 +000082 active; /* user has been given pixel data */
cristy3ed852e2009-09-05 21:47:34 +000083
cristybb503372010-05-27 20:51:26 +000084 ssize_t
cristy3ed852e2009-09-05 21:47:34 +000085 y;
86
87 PixelWand
88 **pixel_wands;
89
90 MagickBooleanType
91 debug;
92
cristybb503372010-05-27 20:51:26 +000093 size_t
cristy3ed852e2009-09-05 21:47:34 +000094 signature;
95};
96
97/*
98%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99% %
100% %
101% %
102% C l e a r P i x e l I t e r a t o r %
103% %
104% %
105% %
106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107%
108% ClearPixelIterator() clear resources associated with a PixelIterator.
109%
110% The format of the ClearPixelIterator method is:
111%
cristy55d68802012-04-25 22:01:06 +0000112% void ClearPixelIterator(PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000113%
114% A description of each parameter follows:
115%
116% o iterator: the pixel iterator.
117%
118*/
119WandExport void ClearPixelIterator(PixelIterator *iterator)
120{
121 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000122 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000123 if (iterator->debug != MagickFalse)
124 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
125 iterator->pixel_wands=DestroyPixelWands(iterator->pixel_wands,
126 iterator->region.width);
127 ClearMagickException(iterator->exception);
128 iterator->pixel_wands=NewPixelWands(iterator->region.width);
129 iterator->active=MagickFalse;
130 iterator->y=0;
131 iterator->debug=IsEventLogging();
132}
133
134/*
135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136% %
137% %
138% %
139% C l o n e P i x e l I t e r a t o r %
140% %
141% %
142% %
143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144%
145% ClonePixelIterator() makes an exact copy of the specified iterator.
146%
147% The format of the ClonePixelIterator method is:
148%
149% PixelIterator *ClonePixelIterator(const PixelIterator *iterator)
150%
151% A description of each parameter follows:
152%
153% o iterator: the magick iterator.
154%
155*/
156WandExport PixelIterator *ClonePixelIterator(const PixelIterator *iterator)
157{
158 PixelIterator
159 *clone_iterator;
160
161 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000162 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000163 if (iterator->debug != MagickFalse)
164 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristy7d5bdf32013-06-30 14:53:50 +0000165 clone_iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*clone_iterator));
cristy3ed852e2009-09-05 21:47:34 +0000166 if (clone_iterator == (PixelIterator *) NULL)
167 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
168 iterator->name);
169 (void) ResetMagickMemory(clone_iterator,0,sizeof(*clone_iterator));
170 clone_iterator->id=AcquireWandId();
cristy151b66d2015-04-15 10:50:31 +0000171 (void) FormatLocaleString(clone_iterator->name,MagickPathExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000172 PixelIteratorId,(double) clone_iterator->id);
cristy3ed852e2009-09-05 21:47:34 +0000173 clone_iterator->exception=AcquireExceptionInfo();
174 InheritException(clone_iterator->exception,iterator->exception);
175 clone_iterator->view=CloneCacheView(iterator->view);
176 clone_iterator->region=iterator->region;
177 clone_iterator->active=iterator->active;
178 clone_iterator->y=iterator->y;
179 clone_iterator->pixel_wands=ClonePixelWands((const PixelWand **)
180 iterator->pixel_wands,iterator->region.width);
181 clone_iterator->debug=iterator->debug;
182 if (clone_iterator->debug != MagickFalse)
183 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",
184 clone_iterator->name);
cristye1c94d92015-06-28 12:16:33 +0000185 clone_iterator->signature=MagickWandSignature;
cristy3ed852e2009-09-05 21:47:34 +0000186 return(clone_iterator);
187}
188
189/*
190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191% %
192% %
193% %
194% D e s t r o y P i x e l I t e r a t o r %
195% %
196% %
197% %
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199%
200% DestroyPixelIterator() deallocates resources associated with a PixelIterator.
201%
202% The format of the DestroyPixelIterator method is:
203%
204% PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
205%
206% A description of each parameter follows:
207%
208% o iterator: the pixel iterator.
209%
210*/
211WandExport PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
212{
213 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000214 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000215 if (iterator->debug != MagickFalse)
216 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
217 iterator->view=DestroyCacheView(iterator->view);
218 iterator->pixel_wands=DestroyPixelWands(iterator->pixel_wands,
219 iterator->region.width);
220 iterator->exception=DestroyExceptionInfo(iterator->exception);
cristye1c94d92015-06-28 12:16:33 +0000221 iterator->signature=(~MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000222 RelinquishWandId(iterator->id);
223 iterator=(PixelIterator *) RelinquishMagickMemory(iterator);
224 return(iterator);
225}
226
227/*
228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229% %
230% %
231% %
232% I s P i x e l I t e r a t o r %
233% %
234% %
235% %
236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237%
238% IsPixelIterator() returns MagickTrue if the iterator is verified as a pixel
239% iterator.
240%
241% The format of the IsPixelIterator method is:
242%
243% MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
244%
245% A description of each parameter follows:
246%
247% o iterator: the magick iterator.
248%
249*/
250WandExport MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
251{
252 size_t
253 length;
254
255 if (iterator == (const PixelIterator *) NULL)
256 return(MagickFalse);
cristye1c94d92015-06-28 12:16:33 +0000257 if (iterator->signature != MagickWandSignature)
cristy3ed852e2009-09-05 21:47:34 +0000258 return(MagickFalse);
259 length=strlen(PixelIteratorId);
260 if (LocaleNCompare(iterator->name,PixelIteratorId,length) != 0)
261 return(MagickFalse);
262 return(MagickTrue);
263}
264
265/*
266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267% %
268% %
269% %
270% N e w P i x e l I t e r a t o r %
271% %
272% %
273% %
274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275%
276% NewPixelIterator() returns a new pixel iterator.
277%
278% The format of the NewPixelIterator method is:
279%
cristy197d0572010-07-29 23:26:05 +0000280% PixelIterator *NewPixelIterator(MagickWand *wand)
cristy3ed852e2009-09-05 21:47:34 +0000281%
282% A description of each parameter follows:
283%
284% o wand: the magick wand.
285%
286*/
287WandExport PixelIterator *NewPixelIterator(MagickWand *wand)
288{
289 const char
290 *quantum;
291
cristydb070952012-04-20 14:33:00 +0000292 ExceptionInfo
293 *exception;
294
cristy3ed852e2009-09-05 21:47:34 +0000295 Image
296 *image;
297
298 PixelIterator
299 *iterator;
300
cristybb503372010-05-27 20:51:26 +0000301 size_t
cristy3ed852e2009-09-05 21:47:34 +0000302 depth;
303
304 CacheView
305 *view;
306
307 depth=MAGICKCORE_QUANTUM_DEPTH;
308 quantum=GetMagickQuantumDepth(&depth);
309 if (depth != MAGICKCORE_QUANTUM_DEPTH)
310 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
311 assert(wand != (MagickWand *) NULL);
312 image=GetImageFromMagickWand(wand);
313 if (image == (Image *) NULL)
314 return((PixelIterator *) NULL);
cristydb070952012-04-20 14:33:00 +0000315 exception=AcquireExceptionInfo();
cristy46ff2672012-12-14 15:32:26 +0000316 view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000317 if (view == (CacheView *) NULL)
318 return((PixelIterator *) NULL);
cristy73bd4a52010-10-05 11:24:23 +0000319 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
cristy3ed852e2009-09-05 21:47:34 +0000320 if (iterator == (PixelIterator *) NULL)
321 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
322 GetExceptionMessage(errno));
323 (void) ResetMagickMemory(iterator,0,sizeof(*iterator));
324 iterator->id=AcquireWandId();
cristy151b66d2015-04-15 10:50:31 +0000325 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000326 PixelIteratorId,(double) iterator->id);
cristydb070952012-04-20 14:33:00 +0000327 iterator->exception=exception;
cristy3ed852e2009-09-05 21:47:34 +0000328 iterator->view=view;
329 SetGeometry(image,&iterator->region);
330 iterator->region.width=image->columns;
331 iterator->region.height=image->rows;
332 iterator->region.x=0;
333 iterator->region.y=0;
334 iterator->pixel_wands=NewPixelWands(iterator->region.width);
335 iterator->y=0;
336 iterator->debug=IsEventLogging();
337 if (iterator->debug != MagickFalse)
338 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristye1c94d92015-06-28 12:16:33 +0000339 iterator->signature=MagickWandSignature;
cristy3ed852e2009-09-05 21:47:34 +0000340 return(iterator);
341}
342
343/*
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345% %
346% %
347% %
348% P i x e l C l e a r I t e r a t o r E x c e p t i o n %
349% %
350% %
351% %
352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353%
354% PixelClearIteratorException() clear any exceptions associated with the
355% iterator.
356%
357% The format of the PixelClearIteratorException method is:
358%
cristy55d68802012-04-25 22:01:06 +0000359% MagickBooleanType PixelClearIteratorException(PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000360%
361% A description of each parameter follows:
362%
cristy55d68802012-04-25 22:01:06 +0000363% o iterator: the pixel iterator.
cristy3ed852e2009-09-05 21:47:34 +0000364%
365*/
366WandExport MagickBooleanType PixelClearIteratorException(
367 PixelIterator *iterator)
368{
369 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000370 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000371 if (iterator->debug != MagickFalse)
372 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
373 ClearMagickException(iterator->exception);
374 return(MagickTrue);
375}
376
377/*
378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379% %
380% %
381% %
382% N e w P i x e l R e g i o n I t e r a t o r %
383% %
384% %
385% %
386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387%
388% NewPixelRegionIterator() returns a new pixel iterator.
389%
390% The format of the NewPixelRegionIterator method is:
391%
cristy0da2c572012-04-26 00:25:37 +0000392% PixelIterator *NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
cristybb503372010-05-27 20:51:26 +0000393% const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000394%
395% A description of each parameter follows:
396%
397% o wand: the magick wand.
398%
399% o x,y,columns,rows: These values define the perimeter of a region of
400% pixels.
401%
402*/
cristy2e8bde02010-06-22 11:03:25 +0000403WandExport PixelIterator *NewPixelRegionIterator(MagickWand *wand,
404 const ssize_t x,const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000405{
cristy2e8bde02010-06-22 11:03:25 +0000406 CacheView
407 *view;
408
cristy3ed852e2009-09-05 21:47:34 +0000409 const char
410 *quantum;
411
cristydb070952012-04-20 14:33:00 +0000412 ExceptionInfo
413 *exception;
414
cristy3ed852e2009-09-05 21:47:34 +0000415 Image
416 *image;
417
418 PixelIterator
419 *iterator;
420
cristybb503372010-05-27 20:51:26 +0000421 size_t
cristy3ed852e2009-09-05 21:47:34 +0000422 depth;
423
cristy3ed852e2009-09-05 21:47:34 +0000424 assert(wand != (MagickWand *) NULL);
425 depth=MAGICKCORE_QUANTUM_DEPTH;
426 quantum=GetMagickQuantumDepth(&depth);
427 if (depth != MAGICKCORE_QUANTUM_DEPTH)
428 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
cristy36ac3432013-12-21 15:04:40 +0000429 if ((width == 0) || (height == 0))
cristy3ed852e2009-09-05 21:47:34 +0000430 ThrowWandFatalException(WandError,"ZeroRegionSize",quantum);
431 image=GetImageFromMagickWand(wand);
432 if (image == (Image *) NULL)
433 return((PixelIterator *) NULL);
cristydb070952012-04-20 14:33:00 +0000434 exception=AcquireExceptionInfo();
cristy46ff2672012-12-14 15:32:26 +0000435 view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000436 if (view == (CacheView *) NULL)
437 return((PixelIterator *) NULL);
cristy73bd4a52010-10-05 11:24:23 +0000438 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
cristy3ed852e2009-09-05 21:47:34 +0000439 if (iterator == (PixelIterator *) NULL)
440 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
441 wand->name);
442 (void) ResetMagickMemory(iterator,0,sizeof(*iterator));
443 iterator->id=AcquireWandId();
cristy151b66d2015-04-15 10:50:31 +0000444 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000445 PixelIteratorId,(double) iterator->id);
cristydb070952012-04-20 14:33:00 +0000446 iterator->exception=exception;
cristy3ed852e2009-09-05 21:47:34 +0000447 iterator->view=view;
448 SetGeometry(image,&iterator->region);
449 iterator->region.width=width;
450 iterator->region.height=height;
451 iterator->region.x=x;
452 iterator->region.y=y;
453 iterator->pixel_wands=NewPixelWands(iterator->region.width);
454 iterator->y=0;
455 iterator->debug=IsEventLogging();
456 if (iterator->debug != MagickFalse)
457 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristye1c94d92015-06-28 12:16:33 +0000458 iterator->signature=MagickWandSignature;
cristy3ed852e2009-09-05 21:47:34 +0000459 return(iterator);
460}
461
462/*
463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464% %
465% %
466% %
467% P i x e l G e t C u r r e n t I t e r a t o r R o w %
468% %
469% %
470% %
471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
472%
473% PixelGetCurrentIteratorRow() returns the current row as an array of pixel
474% wands from the pixel iterator.
475%
476% The format of the PixelGetCurrentIteratorRow method is:
477%
478% PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000479% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000480%
481% A description of each parameter follows:
482%
483% o iterator: the pixel iterator.
484%
485% o number_wands: the number of pixel wands.
486%
487*/
488WandExport PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000489 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000490{
cristy4c08aed2011-07-01 19:47:50 +0000491 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000492 *pixels;
493
cristybb503372010-05-27 20:51:26 +0000494 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000495 x;
496
497 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000498 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000499 if (iterator->debug != MagickFalse)
500 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
501 *number_wands=0;
502 iterator->active=MagickTrue;
503 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
504 iterator->region.y+iterator->y,iterator->region.width,1,
505 iterator->exception);
cristy4c08aed2011-07-01 19:47:50 +0000506 if (pixels == (const Quantum *) NULL)
cristycad4e1b2011-10-16 14:58:39 +0000507 return((PixelWand **) NULL);
cristybb503372010-05-27 20:51:26 +0000508 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000509 {
cristye7516622012-04-29 14:22:45 +0000510 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
511 iterator->pixel_wands[x]);
512 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
cristy4c08aed2011-07-01 19:47:50 +0000513 }
cristy3ed852e2009-09-05 21:47:34 +0000514 *number_wands=iterator->region.width;
515 return(iterator->pixel_wands);
516}
517
518/*
519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520% %
521% %
522% %
523% P i x e l G e t I t e r a t o r E x c e p t i o n %
524% %
525% %
526% %
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528%
529% PixelGetIteratorException() returns the severity, reason, and description of
530% any error that occurs when using other methods in this API.
531%
532% The format of the PixelGetIteratorException method is:
533%
cristy55d68802012-04-25 22:01:06 +0000534% char *PixelGetIteratorException(const PixelIterator *iterator,
cristy3ed852e2009-09-05 21:47:34 +0000535% ExceptionType *severity)
536%
537% A description of each parameter follows:
538%
539% o iterator: the pixel iterator.
540%
541% o severity: the severity of the error is returned here.
542%
543*/
544WandExport char *PixelGetIteratorException(const PixelIterator *iterator,
545 ExceptionType *severity)
546{
547 char
548 *description;
549
550 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000551 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000552 if (iterator->debug != MagickFalse)
553 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
554 assert(severity != (ExceptionType *) NULL);
555 *severity=iterator->exception->severity;
cristy151b66d2015-04-15 10:50:31 +0000556 description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +0000557 sizeof(*description));
558 if (description == (char *) NULL)
559 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
560 iterator->name);
561 *description='\0';
562 if (iterator->exception->reason != (char *) NULL)
563 (void) CopyMagickString(description,GetLocaleExceptionMessage(
cristy151b66d2015-04-15 10:50:31 +0000564 iterator->exception->severity,iterator->exception->reason),MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000565 if (iterator->exception->description != (char *) NULL)
566 {
cristy151b66d2015-04-15 10:50:31 +0000567 (void) ConcatenateMagickString(description," (",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000568 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
569 iterator->exception->severity,iterator->exception->description),
cristy151b66d2015-04-15 10:50:31 +0000570 MagickPathExtent);
571 (void) ConcatenateMagickString(description,")",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000572 }
573 return(description);
574}
575
576/*
577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578% %
579% %
580% %
581% P i x e l G e t E x c e p t i o n T y p e %
582% %
583% %
584% %
585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586%
cristy55d68802012-04-25 22:01:06 +0000587% PixelGetIteratorExceptionType() the exception type associated with the
588% iterator. If no exception has occurred, UndefinedExceptionType is returned.
cristy3ed852e2009-09-05 21:47:34 +0000589%
590% The format of the PixelGetIteratorExceptionType method is:
591%
cristy55d68802012-04-25 22:01:06 +0000592% ExceptionType PixelGetIteratorExceptionType(
593% const PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000594%
595% A description of each parameter follows:
596%
cristy55d68802012-04-25 22:01:06 +0000597% o iterator: the pixel iterator.
cristy3ed852e2009-09-05 21:47:34 +0000598%
599*/
600WandExport ExceptionType PixelGetIteratorExceptionType(
cristy55d68802012-04-25 22:01:06 +0000601 const PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000602{
cristy55d68802012-04-25 22:01:06 +0000603 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000604 assert(iterator->signature == MagickWandSignature);
cristy55d68802012-04-25 22:01:06 +0000605 if (iterator->debug != MagickFalse)
606 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
607 return(iterator->exception->severity);
cristy3ed852e2009-09-05 21:47:34 +0000608}
609
610/*
611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612% %
613% %
614% %
615% P i x e l G e t I t e r a t o r R o w %
616% %
617% %
618% %
619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620%
621% PixelGetIteratorRow() returns the current pixel iterator row.
622%
623% The format of the PixelGetIteratorRow method is:
624%
625% MagickBooleanType PixelGetIteratorRow(PixelIterator *iterator)
626%
627% A description of each parameter follows:
628%
629% o iterator: the pixel iterator.
630%
631*/
cristybb503372010-05-27 20:51:26 +0000632WandExport ssize_t PixelGetIteratorRow(PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000633{
634 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000635 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000636 if (iterator->debug != MagickFalse)
637 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
638 return(iterator->y);
639}
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643% %
644% %
645% %
646% P i x e l G e t N e x t I t e r a t o r R o w %
647% %
648% %
649% %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652% PixelGetNextIteratorRow() returns the next row as an array of pixel wands
653% from the pixel iterator.
654%
655% The format of the PixelGetNextIteratorRow method is:
656%
657% PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000658% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000659%
660% A description of each parameter follows:
661%
662% o iterator: the pixel iterator.
663%
664% o number_wands: the number of pixel wands.
665%
666*/
667WandExport PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000668 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000669{
cristy4c08aed2011-07-01 19:47:50 +0000670 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000671 *pixels;
672
cristybb503372010-05-27 20:51:26 +0000673 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000674 x;
675
676 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000677 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000678 if (iterator->debug != MagickFalse)
679 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
680 *number_wands=0;
681 if (iterator->active != MagickFalse)
682 iterator->y++;
683 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
684 return((PixelWand **) NULL);
685 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
686 iterator->region.y+iterator->y,iterator->region.width,1,
687 iterator->exception);
cristy4c08aed2011-07-01 19:47:50 +0000688 if (pixels == (const Quantum *) NULL)
cristycad4e1b2011-10-16 14:58:39 +0000689 return((PixelWand **) NULL);
cristybb503372010-05-27 20:51:26 +0000690 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000691 {
cristye7516622012-04-29 14:22:45 +0000692 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
693 iterator->pixel_wands[x]);
694 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
cristy4c08aed2011-07-01 19:47:50 +0000695 }
cristy3ed852e2009-09-05 21:47:34 +0000696 *number_wands=iterator->region.width;
697 return(iterator->pixel_wands);
698}
699
700/*
701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702% %
703% %
704% %
705% P i x e l G e t P r e v i o u s I t e r a t o r R o w %
706% %
707% %
708% %
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710%
711% PixelGetPreviousIteratorRow() returns the previous row as an array of pixel
712% wands from the pixel iterator.
713%
714% The format of the PixelGetPreviousIteratorRow method is:
715%
716% PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000717% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000718%
719% A description of each parameter follows:
720%
721% o iterator: the pixel iterator.
722%
723% o number_wands: the number of pixel wands.
724%
725*/
cristy3ed852e2009-09-05 21:47:34 +0000726WandExport PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000727 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000728{
cristy4c08aed2011-07-01 19:47:50 +0000729 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000730 *pixels;
731
cristybb503372010-05-27 20:51:26 +0000732 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000733 x;
734
735 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000736 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000737 if (iterator->debug != MagickFalse)
738 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
739 *number_wands=0;
740 if (iterator->active != MagickFalse)
741 iterator->y--;
742 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
743 return((PixelWand **) NULL);
744 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
745 iterator->region.y+iterator->y,iterator->region.width,1,
746 iterator->exception);
cristy4c08aed2011-07-01 19:47:50 +0000747 if (pixels == (const Quantum *) NULL)
cristycad4e1b2011-10-16 14:58:39 +0000748 return((PixelWand **) NULL);
cristybb503372010-05-27 20:51:26 +0000749 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000750 {
cristye7516622012-04-29 14:22:45 +0000751 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
752 iterator->pixel_wands[x]);
753 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
cristy4c08aed2011-07-01 19:47:50 +0000754 }
cristy3ed852e2009-09-05 21:47:34 +0000755 *number_wands=iterator->region.width;
756 return(iterator->pixel_wands);
757}
758
759/*
760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
761% %
762% %
763% %
764% P i x e l R e s e t I t e r a t o r %
765% %
766% %
767% %
768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
769%
770% PixelResetIterator() resets the pixel iterator. Use it in conjunction
771% with PixelGetNextIteratorRow() to iterate over all the pixels in a pixel
772% container.
773%
774% The format of the PixelResetIterator method is:
775%
776% void PixelResetIterator(PixelIterator *iterator)
777%
778% A description of each parameter follows:
779%
780% o iterator: the pixel iterator.
781%
782*/
783WandExport void PixelResetIterator(PixelIterator *iterator)
784{
785 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000786 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000787 if (iterator->debug != MagickFalse)
788 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
789 iterator->active=MagickFalse;
790 iterator->y=0;
791}
792
793/*
794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795% %
796% %
797% %
798% P i x e l S e t F i r s t I t e r a t o r R o w %
799% %
800% %
801% %
802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803%
804% PixelSetFirstIteratorRow() sets the pixel iterator to the first pixel row.
805%
806% The format of the PixelSetFirstIteratorRow method is:
807%
808% void PixelSetFirstIteratorRow(PixelIterator *iterator)
809%
810% A description of each parameter follows:
811%
812% o iterator: the magick iterator.
813%
814*/
815WandExport void PixelSetFirstIteratorRow(PixelIterator *iterator)
816{
817 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000818 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000819 if (iterator->debug != MagickFalse)
820 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
821 iterator->active=MagickFalse;
822 iterator->y=iterator->region.y;
823}
824
825/*
826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827% %
828% %
829% %
830% P i x e l S e t I t e r a t o r R o w %
831% %
832% %
833% %
834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835%
836% PixelSetIteratorRow() set the pixel iterator row.
837%
838% The format of the PixelSetIteratorRow method is:
839%
840% MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000841% const ssize_t row)
cristy3ed852e2009-09-05 21:47:34 +0000842%
843% A description of each parameter follows:
844%
845% o iterator: the pixel iterator.
846%
847*/
848WandExport MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000849 const ssize_t row)
cristy3ed852e2009-09-05 21:47:34 +0000850{
851 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000852 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000853 if (iterator->debug != MagickFalse)
854 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristybb503372010-05-27 20:51:26 +0000855 if ((row < 0) || (row >= (ssize_t) iterator->region.height))
cristy3ed852e2009-09-05 21:47:34 +0000856 return(MagickFalse);
857 iterator->active=MagickTrue;
858 iterator->y=row;
859 return(MagickTrue);
860}
861
862/*
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864% %
865% %
866% %
867% P i x e l S e t L a s t I t e r a t o r R o w %
868% %
869% %
870% %
871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872%
873% PixelSetLastIteratorRow() sets the pixel iterator to the last pixel row.
874%
875% The format of the PixelSetLastIteratorRow method is:
876%
877% void PixelSetLastIteratorRow(PixelIterator *iterator)
878%
879% A description of each parameter follows:
880%
881% o iterator: the magick iterator.
882%
883*/
884WandExport void PixelSetLastIteratorRow(PixelIterator *iterator)
885{
886 assert(iterator != (PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000887 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000888 if (iterator->debug != MagickFalse)
889 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
890 iterator->active=MagickFalse;
cristybb503372010-05-27 20:51:26 +0000891 iterator->y=(ssize_t) iterator->region.height-1;
cristy3ed852e2009-09-05 21:47:34 +0000892}
893
894/*
895%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896% %
897% %
898% %
899% P i x e l S y n c I t e r a t o r %
900% %
901% %
902% %
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904%
905% PixelSyncIterator() syncs the pixel iterator.
906%
907% The format of the PixelSyncIterator method is:
908%
909% MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
910%
911% A description of each parameter follows:
912%
913% o iterator: the pixel iterator.
914%
915*/
916WandExport MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
917{
cristyc82a27b2011-10-21 01:07:16 +0000918 MagickBooleanType
919 status;
920
cristybb503372010-05-27 20:51:26 +0000921 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000922 x;
923
cristy4c08aed2011-07-01 19:47:50 +0000924 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100925 *_magickcore_restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000926
927 assert(iterator != (const PixelIterator *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000928 assert(iterator->signature == MagickWandSignature);
cristy3ed852e2009-09-05 21:47:34 +0000929 if (iterator->debug != MagickFalse)
930 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristyc82a27b2011-10-21 01:07:16 +0000931 status=SetCacheViewStorageClass(iterator->view,DirectClass,
932 iterator->exception);
933 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000934 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000935 pixels=GetCacheViewAuthenticPixels(iterator->view,iterator->region.x,
cristycad4e1b2011-10-16 14:58:39 +0000936 iterator->region.y+iterator->y,iterator->region.width,1,
937 iterator->exception);
cristy4c08aed2011-07-01 19:47:50 +0000938 if (pixels == (Quantum *) NULL)
cristycad4e1b2011-10-16 14:58:39 +0000939 return(MagickFalse);
cristybb503372010-05-27 20:51:26 +0000940 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy4c08aed2011-07-01 19:47:50 +0000941 {
cristye7516622012-04-29 14:22:45 +0000942 PixelGetQuantumPixel(GetCacheViewImage(iterator->view),
943 iterator->pixel_wands[x],pixels);
944 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
cristy4c08aed2011-07-01 19:47:50 +0000945 }
cristycad4e1b2011-10-16 14:58:39 +0000946 if (SyncCacheViewAuthenticPixels(iterator->view,iterator->exception) == MagickFalse)
947 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000948 return(MagickTrue);
949}