blob: 4fcbb6621c714fbd62aaaab0696939b2af3d027c [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 %
22% John Cristy %
23% March 2003 %
24% %
25% %
cristy7e41fe82010-12-04 23:12:08 +000026% Copyright 1999-2011 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*/
49#include "wand/studio.h"
50#include "wand/MagickWand.h"
51#include "wand/magick-wand-private.h"
52#include "wand/pixel-iterator.h"
53#include "wand/pixel-wand.h"
54#include "wand/wand.h"
55
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
70 name[MaxTextExtent];
71
72 ExceptionInfo
73 *exception;
74
75 CacheView
76 *view;
77
78 RectangleInfo
79 region;
80
81 MagickBooleanType
82 active;
83
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%
112% PixelIterator *ClearPixelIterator(PixelIterator *iterator)
113%
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);
122 assert(iterator->signature == WandSignature);
123 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);
162 assert(iterator->signature == WandSignature);
163 if (iterator->debug != MagickFalse)
164 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristy73bd4a52010-10-05 11:24:23 +0000165 clone_iterator=(PixelIterator *) AcquireMagickMemory(
cristyf2faecf2010-05-28 19:19:36 +0000166 sizeof(*clone_iterator));
cristy3ed852e2009-09-05 21:47:34 +0000167 if (clone_iterator == (PixelIterator *) NULL)
168 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
169 iterator->name);
170 (void) ResetMagickMemory(clone_iterator,0,sizeof(*clone_iterator));
171 clone_iterator->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000172 (void) FormatLocaleString(clone_iterator->name,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000173 PixelIteratorId,(double) clone_iterator->id);
cristy3ed852e2009-09-05 21:47:34 +0000174 clone_iterator->exception=AcquireExceptionInfo();
175 InheritException(clone_iterator->exception,iterator->exception);
176 clone_iterator->view=CloneCacheView(iterator->view);
177 clone_iterator->region=iterator->region;
178 clone_iterator->active=iterator->active;
179 clone_iterator->y=iterator->y;
180 clone_iterator->pixel_wands=ClonePixelWands((const PixelWand **)
181 iterator->pixel_wands,iterator->region.width);
182 clone_iterator->debug=iterator->debug;
183 if (clone_iterator->debug != MagickFalse)
184 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",
185 clone_iterator->name);
186 clone_iterator->signature=WandSignature;
187 return(clone_iterator);
188}
189
190/*
191%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192% %
193% %
194% %
195% D e s t r o y P i x e l I t e r a t o r %
196% %
197% %
198% %
199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200%
201% DestroyPixelIterator() deallocates resources associated with a PixelIterator.
202%
203% The format of the DestroyPixelIterator method is:
204%
205% PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
206%
207% A description of each parameter follows:
208%
209% o iterator: the pixel iterator.
210%
211*/
212WandExport PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
213{
214 assert(iterator != (const PixelIterator *) NULL);
215 assert(iterator->signature == WandSignature);
216 if (iterator->debug != MagickFalse)
217 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
218 iterator->view=DestroyCacheView(iterator->view);
219 iterator->pixel_wands=DestroyPixelWands(iterator->pixel_wands,
220 iterator->region.width);
221 iterator->exception=DestroyExceptionInfo(iterator->exception);
222 iterator->signature=(~WandSignature);
223 RelinquishWandId(iterator->id);
224 iterator=(PixelIterator *) RelinquishMagickMemory(iterator);
225 return(iterator);
226}
227
228/*
229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230% %
231% %
232% %
233% I s P i x e l I t e r a t o r %
234% %
235% %
236% %
237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238%
239% IsPixelIterator() returns MagickTrue if the iterator is verified as a pixel
240% iterator.
241%
242% The format of the IsPixelIterator method is:
243%
244% MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
245%
246% A description of each parameter follows:
247%
248% o iterator: the magick iterator.
249%
250*/
251WandExport MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
252{
253 size_t
254 length;
255
256 if (iterator == (const PixelIterator *) NULL)
257 return(MagickFalse);
258 if (iterator->signature != WandSignature)
259 return(MagickFalse);
260 length=strlen(PixelIteratorId);
261 if (LocaleNCompare(iterator->name,PixelIteratorId,length) != 0)
262 return(MagickFalse);
263 return(MagickTrue);
264}
265
266/*
267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268% %
269% %
270% %
271% N e w P i x e l I t e r a t o r %
272% %
273% %
274% %
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276%
277% NewPixelIterator() returns a new pixel iterator.
278%
279% The format of the NewPixelIterator method is:
280%
cristy197d0572010-07-29 23:26:05 +0000281% PixelIterator *NewPixelIterator(MagickWand *wand)
cristy3ed852e2009-09-05 21:47:34 +0000282%
283% A description of each parameter follows:
284%
285% o wand: the magick wand.
286%
287*/
288WandExport PixelIterator *NewPixelIterator(MagickWand *wand)
289{
290 const char
291 *quantum;
292
293 Image
294 *image;
295
296 PixelIterator
297 *iterator;
298
cristybb503372010-05-27 20:51:26 +0000299 size_t
cristy3ed852e2009-09-05 21:47:34 +0000300 depth;
301
302 CacheView
303 *view;
304
305 depth=MAGICKCORE_QUANTUM_DEPTH;
306 quantum=GetMagickQuantumDepth(&depth);
307 if (depth != MAGICKCORE_QUANTUM_DEPTH)
308 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
309 assert(wand != (MagickWand *) NULL);
310 image=GetImageFromMagickWand(wand);
311 if (image == (Image *) NULL)
312 return((PixelIterator *) NULL);
313 view=AcquireCacheView(image);
314 if (view == (CacheView *) NULL)
315 return((PixelIterator *) NULL);
cristy73bd4a52010-10-05 11:24:23 +0000316 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
cristy3ed852e2009-09-05 21:47:34 +0000317 if (iterator == (PixelIterator *) NULL)
318 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
319 GetExceptionMessage(errno));
320 (void) ResetMagickMemory(iterator,0,sizeof(*iterator));
321 iterator->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000322 (void) FormatLocaleString(iterator->name,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000323 PixelIteratorId,(double) iterator->id);
cristy3ed852e2009-09-05 21:47:34 +0000324 iterator->exception=AcquireExceptionInfo();
325 iterator->view=view;
326 SetGeometry(image,&iterator->region);
327 iterator->region.width=image->columns;
328 iterator->region.height=image->rows;
329 iterator->region.x=0;
330 iterator->region.y=0;
331 iterator->pixel_wands=NewPixelWands(iterator->region.width);
332 iterator->y=0;
333 iterator->debug=IsEventLogging();
334 if (iterator->debug != MagickFalse)
335 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
336 iterator->signature=WandSignature;
337 return(iterator);
338}
339
340/*
341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342% %
343% %
344% %
345% 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 %
346% %
347% %
348% %
349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350%
351% PixelClearIteratorException() clear any exceptions associated with the
352% iterator.
353%
354% The format of the PixelClearIteratorException method is:
355%
356% MagickBooleanType PixelClearIteratorException(PixelIterator *wand)
357%
358% A description of each parameter follows:
359%
360% o wand: the pixel wand.
361%
362*/
363WandExport MagickBooleanType PixelClearIteratorException(
364 PixelIterator *iterator)
365{
366 assert(iterator != (PixelIterator *) NULL);
367 assert(iterator->signature == WandSignature);
368 if (iterator->debug != MagickFalse)
369 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
370 ClearMagickException(iterator->exception);
371 return(MagickTrue);
372}
373
374/*
375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376% %
377% %
378% %
379% N e w P i x e l R e g i o n I t e r a t o r %
380% %
381% %
382% %
383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384%
385% NewPixelRegionIterator() returns a new pixel iterator.
386%
387% The format of the NewPixelRegionIterator method is:
388%
cristybb503372010-05-27 20:51:26 +0000389% PixelIterator NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
390% const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000391%
392% A description of each parameter follows:
393%
394% o wand: the magick wand.
395%
396% o x,y,columns,rows: These values define the perimeter of a region of
397% pixels.
398%
399*/
cristy2e8bde02010-06-22 11:03:25 +0000400WandExport PixelIterator *NewPixelRegionIterator(MagickWand *wand,
401 const ssize_t x,const ssize_t y,const size_t width,const size_t height)
cristy3ed852e2009-09-05 21:47:34 +0000402{
cristy2e8bde02010-06-22 11:03:25 +0000403 CacheView
404 *view;
405
cristy3ed852e2009-09-05 21:47:34 +0000406 const char
407 *quantum;
408
409 Image
410 *image;
411
412 PixelIterator
413 *iterator;
414
cristybb503372010-05-27 20:51:26 +0000415 size_t
cristy3ed852e2009-09-05 21:47:34 +0000416 depth;
417
cristy3ed852e2009-09-05 21:47:34 +0000418 assert(wand != (MagickWand *) NULL);
419 depth=MAGICKCORE_QUANTUM_DEPTH;
420 quantum=GetMagickQuantumDepth(&depth);
421 if (depth != MAGICKCORE_QUANTUM_DEPTH)
422 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
423 if ((width == 0) || (width == 0))
424 ThrowWandFatalException(WandError,"ZeroRegionSize",quantum);
425 image=GetImageFromMagickWand(wand);
426 if (image == (Image *) NULL)
427 return((PixelIterator *) NULL);
428 view=AcquireCacheView(image);
429 if (view == (CacheView *) NULL)
430 return((PixelIterator *) NULL);
cristy73bd4a52010-10-05 11:24:23 +0000431 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
cristy3ed852e2009-09-05 21:47:34 +0000432 if (iterator == (PixelIterator *) NULL)
433 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
434 wand->name);
435 (void) ResetMagickMemory(iterator,0,sizeof(*iterator));
436 iterator->id=AcquireWandId();
cristyb51dff52011-05-19 16:55:47 +0000437 (void) FormatLocaleString(iterator->name,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +0000438 PixelIteratorId,(double) iterator->id);
cristy3ed852e2009-09-05 21:47:34 +0000439 iterator->exception=AcquireExceptionInfo();
440 iterator->view=view;
441 SetGeometry(image,&iterator->region);
442 iterator->region.width=width;
443 iterator->region.height=height;
444 iterator->region.x=x;
445 iterator->region.y=y;
446 iterator->pixel_wands=NewPixelWands(iterator->region.width);
447 iterator->y=0;
448 iterator->debug=IsEventLogging();
449 if (iterator->debug != MagickFalse)
450 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
451 iterator->signature=WandSignature;
452 return(iterator);
453}
454
455/*
456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457% %
458% %
459% %
460% 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 %
461% %
462% %
463% %
464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465%
466% PixelGetCurrentIteratorRow() returns the current row as an array of pixel
467% wands from the pixel iterator.
468%
469% The format of the PixelGetCurrentIteratorRow method is:
470%
471% PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000472% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000473%
474% A description of each parameter follows:
475%
476% o iterator: the pixel iterator.
477%
478% o number_wands: the number of pixel wands.
479%
480*/
481WandExport PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000482 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000483{
484 register const IndexPacket
485 *indexes;
486
487 register const PixelPacket
488 *pixels;
489
cristybb503372010-05-27 20:51:26 +0000490 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000491 x;
492
493 assert(iterator != (PixelIterator *) NULL);
494 assert(iterator->signature == WandSignature);
495 if (iterator->debug != MagickFalse)
496 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
497 *number_wands=0;
498 iterator->active=MagickTrue;
499 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
500 iterator->region.y+iterator->y,iterator->region.width,1,
501 iterator->exception);
502 if (pixels == (const PixelPacket *) NULL)
503 {
504 InheritException(iterator->exception,GetCacheViewException(
505 iterator->view));
506 return((PixelWand **) NULL);
507 }
508 indexes=GetCacheViewVirtualIndexQueue(iterator->view);
cristybb503372010-05-27 20:51:26 +0000509 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy3ed852e2009-09-05 21:47:34 +0000510 PixelSetQuantumColor(iterator->pixel_wands[x],pixels+x);
511 if (GetCacheViewColorspace(iterator->view) == CMYKColorspace)
cristybb503372010-05-27 20:51:26 +0000512 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000513 PixelSetBlackQuantum(iterator->pixel_wands[x],
514 GetBlackPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000515 if (GetCacheViewStorageClass(iterator->view) == PseudoClass)
cristybb503372010-05-27 20:51:26 +0000516 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000517 PixelSetIndex(iterator->pixel_wands[x],
518 GetBlackPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000519 *number_wands=iterator->region.width;
520 return(iterator->pixel_wands);
521}
522
523/*
524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525% %
526% %
527% %
528% 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 %
529% %
530% %
531% %
532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533%
534% PixelGetIteratorException() returns the severity, reason, and description of
535% any error that occurs when using other methods in this API.
536%
537% The format of the PixelGetIteratorException method is:
538%
539% char *PixelGetIteratorException(const Pixeliterator *iterator,
540% ExceptionType *severity)
541%
542% A description of each parameter follows:
543%
544% o iterator: the pixel iterator.
545%
546% o severity: the severity of the error is returned here.
547%
548*/
549WandExport char *PixelGetIteratorException(const PixelIterator *iterator,
550 ExceptionType *severity)
551{
552 char
553 *description;
554
555 assert(iterator != (const PixelIterator *) NULL);
556 assert(iterator->signature == WandSignature);
557 if (iterator->debug != MagickFalse)
558 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
559 assert(severity != (ExceptionType *) NULL);
560 *severity=iterator->exception->severity;
561 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
562 sizeof(*description));
563 if (description == (char *) NULL)
564 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
565 iterator->name);
566 *description='\0';
567 if (iterator->exception->reason != (char *) NULL)
568 (void) CopyMagickString(description,GetLocaleExceptionMessage(
569 iterator->exception->severity,iterator->exception->reason),MaxTextExtent);
570 if (iterator->exception->description != (char *) NULL)
571 {
572 (void) ConcatenateMagickString(description," (",MaxTextExtent);
573 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
574 iterator->exception->severity,iterator->exception->description),
575 MaxTextExtent);
576 (void) ConcatenateMagickString(description,")",MaxTextExtent);
577 }
578 return(description);
579}
580
581/*
582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583% %
584% %
585% %
586% P i x e l G e t E x c e p t i o n T y p e %
587% %
588% %
589% %
590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591%
592% PixelGetIteratorExceptionType() the exception type associated with the wand.
593% If no exception has occurred, UndefinedExceptionType is returned.
594%
595% The format of the PixelGetIteratorExceptionType method is:
596%
597% ExceptionType PixelGetIteratorExceptionType(const PixelWand *wand)
598%
599% A description of each parameter follows:
600%
601% o wand: the magick wand.
602%
603*/
604WandExport ExceptionType PixelGetIteratorExceptionType(
605 const PixelIterator *wand)
606{
607 assert(wand != (const PixelIterator *) NULL);
608 assert(wand->signature == WandSignature);
609 if (wand->debug != MagickFalse)
610 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
611 return(wand->exception->severity);
612}
613
614/*
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616% %
617% %
618% %
619% P i x e l G e t I t e r a t o r R o w %
620% %
621% %
622% %
623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624%
625% PixelGetIteratorRow() returns the current pixel iterator row.
626%
627% The format of the PixelGetIteratorRow method is:
628%
629% MagickBooleanType PixelGetIteratorRow(PixelIterator *iterator)
630%
631% A description of each parameter follows:
632%
633% o iterator: the pixel iterator.
634%
635*/
cristybb503372010-05-27 20:51:26 +0000636WandExport ssize_t PixelGetIteratorRow(PixelIterator *iterator)
cristy3ed852e2009-09-05 21:47:34 +0000637{
638 assert(iterator != (const PixelIterator *) NULL);
639 assert(iterator->signature == WandSignature);
640 if (iterator->debug != MagickFalse)
641 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
642 return(iterator->y);
643}
644
645/*
646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647% %
648% %
649% %
650% P i x e l G e t N e x t I t e r a t o r R o w %
651% %
652% %
653% %
654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655%
656% PixelGetNextIteratorRow() returns the next row as an array of pixel wands
657% from the pixel iterator.
658%
659% The format of the PixelGetNextIteratorRow method is:
660%
661% PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000662% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000663%
664% A description of each parameter follows:
665%
666% o iterator: the pixel iterator.
667%
668% o number_wands: the number of pixel wands.
669%
670*/
671WandExport PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000672 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000673{
674 register const IndexPacket
675 *indexes;
676
677 register const PixelPacket
678 *pixels;
679
cristybb503372010-05-27 20:51:26 +0000680 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000681 x;
682
683 assert(iterator != (PixelIterator *) NULL);
684 assert(iterator->signature == WandSignature);
685 if (iterator->debug != MagickFalse)
686 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
687 *number_wands=0;
688 if (iterator->active != MagickFalse)
689 iterator->y++;
690 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
691 return((PixelWand **) NULL);
692 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
693 iterator->region.y+iterator->y,iterator->region.width,1,
694 iterator->exception);
695 if (pixels == (const PixelPacket *) NULL)
696 {
697 InheritException(iterator->exception,GetCacheViewException(
698 iterator->view));
699 return((PixelWand **) NULL);
700 }
701 indexes=GetCacheViewVirtualIndexQueue(iterator->view);
cristybb503372010-05-27 20:51:26 +0000702 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy3ed852e2009-09-05 21:47:34 +0000703 PixelSetQuantumColor(iterator->pixel_wands[x],pixels+x);
704 if (GetCacheViewColorspace(iterator->view) == CMYKColorspace)
cristybb503372010-05-27 20:51:26 +0000705 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000706 PixelSetBlackQuantum(iterator->pixel_wands[x],
707 GetBlackPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000708 if (GetCacheViewStorageClass(iterator->view) == PseudoClass)
cristybb503372010-05-27 20:51:26 +0000709 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000710 PixelSetIndex(iterator->pixel_wands[x],
711 GetIndexPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000712 *number_wands=iterator->region.width;
713 return(iterator->pixel_wands);
714}
715
716/*
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718% %
719% %
720% %
721% 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 %
722% %
723% %
724% %
725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726%
727% PixelGetPreviousIteratorRow() returns the previous row as an array of pixel
728% wands from the pixel iterator.
729%
730% The format of the PixelGetPreviousIteratorRow method is:
731%
732% PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000733% size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000734%
735% A description of each parameter follows:
736%
737% o iterator: the pixel iterator.
738%
739% o number_wands: the number of pixel wands.
740%
741*/
742
743WandExport PixelWand **PixelGetPreviousRow(PixelIterator *iterator)
744{
cristybb503372010-05-27 20:51:26 +0000745 size_t
cristy3ed852e2009-09-05 21:47:34 +0000746 number_wands;
747
748 return(PixelGetPreviousIteratorRow(iterator,&number_wands));
749}
750
751WandExport PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000752 size_t *number_wands)
cristy3ed852e2009-09-05 21:47:34 +0000753{
754 register const IndexPacket
755 *indexes;
756
757 register const PixelPacket
758 *pixels;
759
cristybb503372010-05-27 20:51:26 +0000760 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000761 x;
762
763 assert(iterator != (PixelIterator *) NULL);
764 assert(iterator->signature == WandSignature);
765 if (iterator->debug != MagickFalse)
766 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
767 *number_wands=0;
768 if (iterator->active != MagickFalse)
769 iterator->y--;
770 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
771 return((PixelWand **) NULL);
772 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
773 iterator->region.y+iterator->y,iterator->region.width,1,
774 iterator->exception);
775 if (pixels == (const PixelPacket *) NULL)
776 {
777 InheritException(iterator->exception,GetCacheViewException(
778 iterator->view));
779 return((PixelWand **) NULL);
780 }
781 indexes=GetCacheViewVirtualIndexQueue(iterator->view);
cristybb503372010-05-27 20:51:26 +0000782 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy3ed852e2009-09-05 21:47:34 +0000783 PixelSetQuantumColor(iterator->pixel_wands[x],pixels+x);
784 if (GetCacheViewColorspace(iterator->view) == CMYKColorspace)
cristybb503372010-05-27 20:51:26 +0000785 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000786 PixelSetBlackQuantum(iterator->pixel_wands[x],
787 GetBlackPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000788 if (GetCacheViewStorageClass(iterator->view) == PseudoClass)
cristybb503372010-05-27 20:51:26 +0000789 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000790 PixelSetIndex(iterator->pixel_wands[x],
791 GetIndexPixelComponent(indexes+x));
cristy3ed852e2009-09-05 21:47:34 +0000792 *number_wands=iterator->region.width;
793 return(iterator->pixel_wands);
794}
795
796/*
797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798% %
799% %
800% %
801% P i x e l R e s e t I t e r a t o r %
802% %
803% %
804% %
805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806%
807% PixelResetIterator() resets the pixel iterator. Use it in conjunction
808% with PixelGetNextIteratorRow() to iterate over all the pixels in a pixel
809% container.
810%
811% The format of the PixelResetIterator method is:
812%
813% void PixelResetIterator(PixelIterator *iterator)
814%
815% A description of each parameter follows:
816%
817% o iterator: the pixel iterator.
818%
819*/
820WandExport void PixelResetIterator(PixelIterator *iterator)
821{
822 assert(iterator != (PixelIterator *) NULL);
823 assert(iterator->signature == WandSignature);
824 if (iterator->debug != MagickFalse)
825 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
826 iterator->active=MagickFalse;
827 iterator->y=0;
828}
829
830/*
831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832% %
833% %
834% %
835% P i x e l S e t F i r s t I t e r a t o r R o w %
836% %
837% %
838% %
839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840%
841% PixelSetFirstIteratorRow() sets the pixel iterator to the first pixel row.
842%
843% The format of the PixelSetFirstIteratorRow method is:
844%
845% void PixelSetFirstIteratorRow(PixelIterator *iterator)
846%
847% A description of each parameter follows:
848%
849% o iterator: the magick iterator.
850%
851*/
852WandExport void PixelSetFirstIteratorRow(PixelIterator *iterator)
853{
854 assert(iterator != (PixelIterator *) NULL);
855 assert(iterator->signature == WandSignature);
856 if (iterator->debug != MagickFalse)
857 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
858 iterator->active=MagickFalse;
859 iterator->y=iterator->region.y;
860}
861
862/*
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864% %
865% %
866% %
867% P i x e l S e t I t e r a t o r R o w %
868% %
869% %
870% %
871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872%
873% PixelSetIteratorRow() set the pixel iterator row.
874%
875% The format of the PixelSetIteratorRow method is:
876%
877% MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000878% const ssize_t row)
cristy3ed852e2009-09-05 21:47:34 +0000879%
880% A description of each parameter follows:
881%
882% o iterator: the pixel iterator.
883%
884*/
885WandExport MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
cristybb503372010-05-27 20:51:26 +0000886 const ssize_t row)
cristy3ed852e2009-09-05 21:47:34 +0000887{
888 assert(iterator != (const PixelIterator *) NULL);
889 assert(iterator->signature == WandSignature);
890 if (iterator->debug != MagickFalse)
891 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
cristybb503372010-05-27 20:51:26 +0000892 if ((row < 0) || (row >= (ssize_t) iterator->region.height))
cristy3ed852e2009-09-05 21:47:34 +0000893 return(MagickFalse);
894 iterator->active=MagickTrue;
895 iterator->y=row;
896 return(MagickTrue);
897}
898
899/*
900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901% %
902% %
903% %
904% P i x e l S e t L a s t I t e r a t o r R o w %
905% %
906% %
907% %
908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909%
910% PixelSetLastIteratorRow() sets the pixel iterator to the last pixel row.
911%
912% The format of the PixelSetLastIteratorRow method is:
913%
914% void PixelSetLastIteratorRow(PixelIterator *iterator)
915%
916% A description of each parameter follows:
917%
918% o iterator: the magick iterator.
919%
920*/
921WandExport void PixelSetLastIteratorRow(PixelIterator *iterator)
922{
923 assert(iterator != (PixelIterator *) NULL);
924 assert(iterator->signature == WandSignature);
925 if (iterator->debug != MagickFalse)
926 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
927 iterator->active=MagickFalse;
cristybb503372010-05-27 20:51:26 +0000928 iterator->y=(ssize_t) iterator->region.height-1;
cristy3ed852e2009-09-05 21:47:34 +0000929}
930
931/*
932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
933% %
934% %
935% %
936% P i x e l S y n c I t e r a t o r %
937% %
938% %
939% %
940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
941%
942% PixelSyncIterator() syncs the pixel iterator.
943%
944% The format of the PixelSyncIterator method is:
945%
946% MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
947%
948% A description of each parameter follows:
949%
950% o iterator: the pixel iterator.
951%
952*/
953WandExport MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
954{
955 ExceptionInfo
956 *exception;
957
958 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000959 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000960
cristybb503372010-05-27 20:51:26 +0000961 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000962 x;
963
964 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000965 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000966
967 assert(iterator != (const PixelIterator *) NULL);
968 assert(iterator->signature == WandSignature);
969 if (iterator->debug != MagickFalse)
970 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
971 if (SetCacheViewStorageClass(iterator->view,DirectClass) == MagickFalse)
972 return(MagickFalse);
973 exception=iterator->exception;
974 pixels=GetCacheViewAuthenticPixels(iterator->view,iterator->region.x,
975 iterator->region.y+iterator->y,iterator->region.width,1,exception);
976 if (pixels == (PixelPacket *) NULL)
977 {
978 InheritException(iterator->exception,GetCacheViewException(
979 iterator->view));
980 return(MagickFalse);
981 }
982 indexes=GetCacheViewAuthenticIndexQueue(iterator->view);
cristybb503372010-05-27 20:51:26 +0000983 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy3ed852e2009-09-05 21:47:34 +0000984 PixelGetQuantumColor(iterator->pixel_wands[x],pixels+x);
985 if (GetCacheViewColorspace(iterator->view) == CMYKColorspace)
cristybb503372010-05-27 20:51:26 +0000986 for (x=0; x < (ssize_t) iterator->region.width; x++)
cristy843c1722011-05-04 23:47:02 +0000987 SetBlackPixelComponent(indexes+x,PixelGetBlackQuantum(
988 iterator->pixel_wands[x]));
cristy3ed852e2009-09-05 21:47:34 +0000989 if (SyncCacheViewAuthenticPixels(iterator->view,exception) == MagickFalse)
990 {
991 InheritException(iterator->exception,GetCacheViewException(
992 iterator->view));
993 return(MagickFalse);
994 }
995 return(MagickTrue);
996}