1 /*
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 % Cristy %
23 % March 2003 %
24 % %
25 % %
26 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
27 % 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 % https://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 "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"
55
56 /*
57 Define declarations.
58 */
59 #define PixelIteratorId "PixelIterator"
60
61 /*
62 Typedef declarations.
63 */
64 struct _PixelIterator
65 {
66 size_t
67 id;
68
69 char
70 name[MagickPathExtent];
71
72 ExceptionInfo
73 *exception;
74
75 CacheView
76 *view;
77
78 RectangleInfo
79 region;
80
81 MagickBooleanType
82 active; /* user has been given pixel data */
83
84 ssize_t
85 y;
86
87 PixelWand
88 **pixel_wands;
89
90 MagickBooleanType
91 debug;
92
93 size_t
94 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 % void ClearPixelIterator(PixelIterator *iterator)
113 %
114 % A description of each parameter follows:
115 %
116 % o iterator: the pixel iterator.
117 %
118 */
ClearPixelIterator(PixelIterator * iterator)119 WandExport void ClearPixelIterator(PixelIterator *iterator)
120 {
121 assert(iterator != (const PixelIterator *) NULL);
122 assert(iterator->signature == MagickWandSignature);
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 */
ClonePixelIterator(const PixelIterator * iterator)156 WandExport PixelIterator *ClonePixelIterator(const PixelIterator *iterator)
157 {
158 PixelIterator
159 *clone_iterator;
160
161 assert(iterator != (PixelIterator *) NULL);
162 assert(iterator->signature == MagickWandSignature);
163 if (iterator->debug != MagickFalse)
164 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
165 clone_iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*clone_iterator));
166 if (clone_iterator == (PixelIterator *) NULL)
167 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
168 iterator->name);
169 (void) memset(clone_iterator,0,sizeof(*clone_iterator));
170 clone_iterator->id=AcquireWandId();
171 (void) FormatLocaleString(clone_iterator->name,MagickPathExtent,"%s-%.20g",
172 PixelIteratorId,(double) clone_iterator->id);
173 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);
185 clone_iterator->signature=MagickWandSignature;
186 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 */
DestroyPixelIterator(PixelIterator * iterator)211 WandExport PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
212 {
213 assert(iterator != (const PixelIterator *) NULL);
214 assert(iterator->signature == MagickWandSignature);
215 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);
221 iterator->signature=(~MagickWandSignature);
222 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 */
IsPixelIterator(const PixelIterator * iterator)250 WandExport MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
251 {
252 size_t
253 length;
254
255 if (iterator == (const PixelIterator *) NULL)
256 return(MagickFalse);
257 if (iterator->signature != MagickWandSignature)
258 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 %
280 % PixelIterator *NewPixelIterator(MagickWand *wand)
281 %
282 % A description of each parameter follows:
283 %
284 % o wand: the magick wand.
285 %
286 */
NewPixelIterator(MagickWand * wand)287 WandExport PixelIterator *NewPixelIterator(MagickWand *wand)
288 {
289 const char
290 *quantum;
291
292 ExceptionInfo
293 *exception;
294
295 Image
296 *image;
297
298 PixelIterator
299 *iterator;
300
301 size_t
302 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);
315 exception=AcquireExceptionInfo();
316 view=AcquireVirtualCacheView(image,exception);
317 if (view == (CacheView *) NULL)
318 return((PixelIterator *) NULL);
319 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
320 if (iterator == (PixelIterator *) NULL)
321 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
322 GetExceptionMessage(errno));
323 (void) memset(iterator,0,sizeof(*iterator));
324 iterator->id=AcquireWandId();
325 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
326 PixelIteratorId,(double) iterator->id);
327 iterator->exception=exception;
328 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);
339 iterator->signature=MagickWandSignature;
340 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 %
359 % MagickBooleanType PixelClearIteratorException(PixelIterator *iterator)
360 %
361 % A description of each parameter follows:
362 %
363 % o iterator: the pixel iterator.
364 %
365 */
PixelClearIteratorException(PixelIterator * iterator)366 WandExport MagickBooleanType PixelClearIteratorException(
367 PixelIterator *iterator)
368 {
369 assert(iterator != (PixelIterator *) NULL);
370 assert(iterator->signature == MagickWandSignature);
371 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 %
392 % PixelIterator *NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
393 % const ssize_t y,const size_t width,const size_t height)
394 %
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 */
NewPixelRegionIterator(MagickWand * wand,const ssize_t x,const ssize_t y,const size_t width,const size_t height)403 WandExport PixelIterator *NewPixelRegionIterator(MagickWand *wand,
404 const ssize_t x,const ssize_t y,const size_t width,const size_t height)
405 {
406 CacheView
407 *view;
408
409 const char
410 *quantum;
411
412 ExceptionInfo
413 *exception;
414
415 Image
416 *image;
417
418 PixelIterator
419 *iterator;
420
421 size_t
422 depth;
423
424 assert(wand != (MagickWand *) NULL);
425 depth=MAGICKCORE_QUANTUM_DEPTH;
426 quantum=GetMagickQuantumDepth(&depth);
427 if (depth != MAGICKCORE_QUANTUM_DEPTH)
428 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
429 if ((width == 0) || (height == 0))
430 ThrowWandFatalException(WandError,"ZeroRegionSize",quantum);
431 image=GetImageFromMagickWand(wand);
432 if (image == (Image *) NULL)
433 return((PixelIterator *) NULL);
434 exception=AcquireExceptionInfo();
435 view=AcquireVirtualCacheView(image,exception);
436 if (view == (CacheView *) NULL)
437 return((PixelIterator *) NULL);
438 iterator=(PixelIterator *) AcquireMagickMemory(sizeof(*iterator));
439 if (iterator == (PixelIterator *) NULL)
440 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
441 wand->name);
442 (void) memset(iterator,0,sizeof(*iterator));
443 iterator->id=AcquireWandId();
444 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
445 PixelIteratorId,(double) iterator->id);
446 iterator->exception=exception;
447 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);
458 iterator->signature=MagickWandSignature;
459 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,
479 % size_t *number_wands)
480 %
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 */
PixelGetCurrentIteratorRow(PixelIterator * iterator,size_t * number_wands)488 WandExport PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
489 size_t *number_wands)
490 {
491 register const Quantum
492 *pixels;
493
494 register ssize_t
495 x;
496
497 assert(iterator != (PixelIterator *) NULL);
498 assert(iterator->signature == MagickWandSignature);
499 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);
506 if (pixels == (const Quantum *) NULL)
507 return((PixelWand **) NULL);
508 for (x=0; x < (ssize_t) iterator->region.width; x++)
509 {
510 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
511 iterator->pixel_wands[x]);
512 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
513 }
514 *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 %
534 % char *PixelGetIteratorException(const PixelIterator *iterator,
535 % 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 */
PixelGetIteratorException(const PixelIterator * iterator,ExceptionType * severity)544 WandExport char *PixelGetIteratorException(const PixelIterator *iterator,
545 ExceptionType *severity)
546 {
547 char
548 *description;
549
550 assert(iterator != (const PixelIterator *) NULL);
551 assert(iterator->signature == MagickWandSignature);
552 if (iterator->debug != MagickFalse)
553 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
554 assert(severity != (ExceptionType *) NULL);
555 *severity=iterator->exception->severity;
556 description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
557 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(
564 iterator->exception->severity,iterator->exception->reason),MagickPathExtent);
565 if (iterator->exception->description != (char *) NULL)
566 {
567 (void) ConcatenateMagickString(description," (",MagickPathExtent);
568 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
569 iterator->exception->severity,iterator->exception->description),
570 MagickPathExtent);
571 (void) ConcatenateMagickString(description,")",MagickPathExtent);
572 }
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 %
587 % PixelGetIteratorExceptionType() the exception type associated with the
588 % iterator. If no exception has occurred, UndefinedExceptionType is returned.
589 %
590 % The format of the PixelGetIteratorExceptionType method is:
591 %
592 % ExceptionType PixelGetIteratorExceptionType(
593 % const PixelIterator *iterator)
594 %
595 % A description of each parameter follows:
596 %
597 % o iterator: the pixel iterator.
598 %
599 */
PixelGetIteratorExceptionType(const PixelIterator * iterator)600 WandExport ExceptionType PixelGetIteratorExceptionType(
601 const PixelIterator *iterator)
602 {
603 assert(iterator != (const PixelIterator *) NULL);
604 assert(iterator->signature == MagickWandSignature);
605 if (iterator->debug != MagickFalse)
606 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
607 return(iterator->exception->severity);
608 }
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 */
PixelGetIteratorRow(PixelIterator * iterator)632 WandExport ssize_t PixelGetIteratorRow(PixelIterator *iterator)
633 {
634 assert(iterator != (const PixelIterator *) NULL);
635 assert(iterator->signature == MagickWandSignature);
636 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,
658 % size_t *number_wands)
659 %
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 */
PixelGetNextIteratorRow(PixelIterator * iterator,size_t * number_wands)667 WandExport PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
668 size_t *number_wands)
669 {
670 register const Quantum
671 *pixels;
672
673 register ssize_t
674 x;
675
676 assert(iterator != (PixelIterator *) NULL);
677 assert(iterator->signature == MagickWandSignature);
678 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);
688 if (pixels == (const Quantum *) NULL)
689 return((PixelWand **) NULL);
690 for (x=0; x < (ssize_t) iterator->region.width; x++)
691 {
692 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
693 iterator->pixel_wands[x]);
694 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
695 }
696 *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,
717 % size_t *number_wands)
718 %
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 */
PixelGetPreviousIteratorRow(PixelIterator * iterator,size_t * number_wands)726 WandExport PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
727 size_t *number_wands)
728 {
729 register const Quantum
730 *pixels;
731
732 register ssize_t
733 x;
734
735 assert(iterator != (PixelIterator *) NULL);
736 assert(iterator->signature == MagickWandSignature);
737 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);
747 if (pixels == (const Quantum *) NULL)
748 return((PixelWand **) NULL);
749 for (x=0; x < (ssize_t) iterator->region.width; x++)
750 {
751 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
752 iterator->pixel_wands[x]);
753 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
754 }
755 *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 */
PixelResetIterator(PixelIterator * iterator)783 WandExport void PixelResetIterator(PixelIterator *iterator)
784 {
785 assert(iterator != (PixelIterator *) NULL);
786 assert(iterator->signature == MagickWandSignature);
787 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 */
PixelSetFirstIteratorRow(PixelIterator * iterator)815 WandExport void PixelSetFirstIteratorRow(PixelIterator *iterator)
816 {
817 assert(iterator != (PixelIterator *) NULL);
818 assert(iterator->signature == MagickWandSignature);
819 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,
841 % const ssize_t row)
842 %
843 % A description of each parameter follows:
844 %
845 % o iterator: the pixel iterator.
846 %
847 */
PixelSetIteratorRow(PixelIterator * iterator,const ssize_t row)848 WandExport MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
849 const ssize_t row)
850 {
851 assert(iterator != (const PixelIterator *) NULL);
852 assert(iterator->signature == MagickWandSignature);
853 if (iterator->debug != MagickFalse)
854 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
855 if ((row < 0) || (row >= (ssize_t) iterator->region.height))
856 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 */
PixelSetLastIteratorRow(PixelIterator * iterator)884 WandExport void PixelSetLastIteratorRow(PixelIterator *iterator)
885 {
886 assert(iterator != (PixelIterator *) NULL);
887 assert(iterator->signature == MagickWandSignature);
888 if (iterator->debug != MagickFalse)
889 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
890 iterator->active=MagickFalse;
891 iterator->y=(ssize_t) iterator->region.height-1;
892 }
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 */
PixelSyncIterator(PixelIterator * iterator)916 WandExport MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
917 {
918 MagickBooleanType
919 status;
920
921 register ssize_t
922 x;
923
924 register Quantum
925 *_magickcore_restrict pixels;
926
927 assert(iterator != (const PixelIterator *) NULL);
928 assert(iterator->signature == MagickWandSignature);
929 if (iterator->debug != MagickFalse)
930 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
931 status=SetCacheViewStorageClass(iterator->view,DirectClass,
932 iterator->exception);
933 if (status == MagickFalse)
934 return(MagickFalse);
935 pixels=GetCacheViewAuthenticPixels(iterator->view,iterator->region.x,
936 iterator->region.y+iterator->y,iterator->region.width,1,
937 iterator->exception);
938 if (pixels == (Quantum *) NULL)
939 return(MagickFalse);
940 for (x=0; x < (ssize_t) iterator->region.width; x++)
941 {
942 PixelGetQuantumPixel(GetCacheViewImage(iterator->view),
943 iterator->pixel_wands[x],pixels);
944 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
945 }
946 if (SyncCacheViewAuthenticPixels(iterator->view,iterator->exception) == MagickFalse)
947 return(MagickFalse);
948 return(MagickTrue);
949 }
950