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-2021 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 *) AcquireCriticalMemory(
166 sizeof(*clone_iterator));
167 (void) memset(clone_iterator,0,sizeof(*clone_iterator));
168 clone_iterator->id=AcquireWandId();
169 (void) FormatLocaleString(clone_iterator->name,MagickPathExtent,"%s-%.20g",
170 PixelIteratorId,(double) clone_iterator->id);
171 clone_iterator->exception=AcquireExceptionInfo();
172 InheritException(clone_iterator->exception,iterator->exception);
173 clone_iterator->view=CloneCacheView(iterator->view);
174 clone_iterator->region=iterator->region;
175 clone_iterator->active=iterator->active;
176 clone_iterator->y=iterator->y;
177 clone_iterator->pixel_wands=ClonePixelWands((const PixelWand **)
178 iterator->pixel_wands,iterator->region.width);
179 clone_iterator->debug=iterator->debug;
180 if (clone_iterator->debug != MagickFalse)
181 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",
182 clone_iterator->name);
183 clone_iterator->signature=MagickWandSignature;
184 return(clone_iterator);
185 }
186
187 /*
188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189 % %
190 % %
191 % %
192 % D e s t r o y P i x e l I t e r a t o r %
193 % %
194 % %
195 % %
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 %
198 % DestroyPixelIterator() deallocates resources associated with a PixelIterator.
199 %
200 % The format of the DestroyPixelIterator method is:
201 %
202 % PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
203 %
204 % A description of each parameter follows:
205 %
206 % o iterator: the pixel iterator.
207 %
208 */
DestroyPixelIterator(PixelIterator * iterator)209 WandExport PixelIterator *DestroyPixelIterator(PixelIterator *iterator)
210 {
211 assert(iterator != (const PixelIterator *) NULL);
212 assert(iterator->signature == MagickWandSignature);
213 if (iterator->debug != MagickFalse)
214 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
215 iterator->view=DestroyCacheView(iterator->view);
216 iterator->pixel_wands=DestroyPixelWands(iterator->pixel_wands,
217 iterator->region.width);
218 iterator->exception=DestroyExceptionInfo(iterator->exception);
219 iterator->signature=(~MagickWandSignature);
220 RelinquishWandId(iterator->id);
221 iterator=(PixelIterator *) RelinquishMagickMemory(iterator);
222 return(iterator);
223 }
224
225 /*
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 % %
228 % %
229 % %
230 % I s P i x e l I t e r a t o r %
231 % %
232 % %
233 % %
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 %
236 % IsPixelIterator() returns MagickTrue if the iterator is verified as a pixel
237 % iterator.
238 %
239 % The format of the IsPixelIterator method is:
240 %
241 % MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
242 %
243 % A description of each parameter follows:
244 %
245 % o iterator: the magick iterator.
246 %
247 */
IsPixelIterator(const PixelIterator * iterator)248 WandExport MagickBooleanType IsPixelIterator(const PixelIterator *iterator)
249 {
250 size_t
251 length;
252
253 if (iterator == (const PixelIterator *) NULL)
254 return(MagickFalse);
255 if (iterator->signature != MagickWandSignature)
256 return(MagickFalse);
257 length=strlen(PixelIteratorId);
258 if (LocaleNCompare(iterator->name,PixelIteratorId,length) != 0)
259 return(MagickFalse);
260 return(MagickTrue);
261 }
262
263 /*
264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265 % %
266 % %
267 % %
268 % N e w P i x e l I t e r a t o r %
269 % %
270 % %
271 % %
272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273 %
274 % NewPixelIterator() returns a new pixel iterator.
275 %
276 % The format of the NewPixelIterator method is:
277 %
278 % PixelIterator *NewPixelIterator(MagickWand *wand)
279 %
280 % A description of each parameter follows:
281 %
282 % o wand: the magick wand.
283 %
284 */
NewPixelIterator(MagickWand * wand)285 WandExport PixelIterator *NewPixelIterator(MagickWand *wand)
286 {
287 const char
288 *quantum;
289
290 ExceptionInfo
291 *exception;
292
293 Image
294 *image;
295
296 PixelIterator
297 *iterator;
298
299 size_t
300 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 exception=AcquireExceptionInfo();
314 view=AcquireVirtualCacheView(image,exception);
315 if (view == (CacheView *) NULL)
316 return((PixelIterator *) NULL);
317 iterator=(PixelIterator *) AcquireCriticalMemory(sizeof(*iterator));
318 (void) memset(iterator,0,sizeof(*iterator));
319 iterator->id=AcquireWandId();
320 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
321 PixelIteratorId,(double) iterator->id);
322 iterator->exception=exception;
323 iterator->view=view;
324 SetGeometry(image,&iterator->region);
325 iterator->region.width=image->columns;
326 iterator->region.height=image->rows;
327 iterator->region.x=0;
328 iterator->region.y=0;
329 iterator->pixel_wands=NewPixelWands(iterator->region.width);
330 iterator->y=0;
331 iterator->debug=IsEventLogging();
332 if (iterator->debug != MagickFalse)
333 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
334 iterator->signature=MagickWandSignature;
335 return(iterator);
336 }
337
338 /*
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % %
341 % %
342 % %
343 % 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 %
344 % %
345 % %
346 % %
347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348 %
349 % PixelClearIteratorException() clear any exceptions associated with the
350 % iterator.
351 %
352 % The format of the PixelClearIteratorException method is:
353 %
354 % MagickBooleanType PixelClearIteratorException(PixelIterator *iterator)
355 %
356 % A description of each parameter follows:
357 %
358 % o iterator: the pixel iterator.
359 %
360 */
PixelClearIteratorException(PixelIterator * iterator)361 WandExport MagickBooleanType PixelClearIteratorException(
362 PixelIterator *iterator)
363 {
364 assert(iterator != (PixelIterator *) NULL);
365 assert(iterator->signature == MagickWandSignature);
366 if (iterator->debug != MagickFalse)
367 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
368 ClearMagickException(iterator->exception);
369 return(MagickTrue);
370 }
371
372 /*
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 % %
375 % %
376 % %
377 % N e w P i x e l R e g i o n I t e r a t o r %
378 % %
379 % %
380 % %
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 %
383 % NewPixelRegionIterator() returns a new pixel iterator.
384 %
385 % The format of the NewPixelRegionIterator method is:
386 %
387 % PixelIterator *NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
388 % const ssize_t y,const size_t width,const size_t height)
389 %
390 % A description of each parameter follows:
391 %
392 % o wand: the magick wand.
393 %
394 % o x,y,columns,rows: These values define the perimeter of a region of
395 % pixels.
396 %
397 */
NewPixelRegionIterator(MagickWand * wand,const ssize_t x,const ssize_t y,const size_t width,const size_t height)398 WandExport PixelIterator *NewPixelRegionIterator(MagickWand *wand,
399 const ssize_t x,const ssize_t y,const size_t width,const size_t height)
400 {
401 CacheView
402 *view;
403
404 const char
405 *quantum;
406
407 ExceptionInfo
408 *exception;
409
410 Image
411 *image;
412
413 PixelIterator
414 *iterator;
415
416 size_t
417 depth;
418
419 assert(wand != (MagickWand *) NULL);
420 depth=MAGICKCORE_QUANTUM_DEPTH;
421 quantum=GetMagickQuantumDepth(&depth);
422 if (depth != MAGICKCORE_QUANTUM_DEPTH)
423 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
424 if ((width == 0) || (height == 0))
425 ThrowWandFatalException(WandError,"ZeroRegionSize",quantum);
426 image=GetImageFromMagickWand(wand);
427 if (image == (Image *) NULL)
428 return((PixelIterator *) NULL);
429 exception=AcquireExceptionInfo();
430 view=AcquireVirtualCacheView(image,exception);
431 if (view == (CacheView *) NULL)
432 return((PixelIterator *) NULL);
433 iterator=(PixelIterator *) AcquireCriticalMemory(sizeof(*iterator));
434 (void) memset(iterator,0,sizeof(*iterator));
435 iterator->id=AcquireWandId();
436 (void) FormatLocaleString(iterator->name,MagickPathExtent,"%s-%.20g",
437 PixelIteratorId,(double) iterator->id);
438 iterator->exception=exception;
439 iterator->view=view;
440 SetGeometry(image,&iterator->region);
441 iterator->region.width=width;
442 iterator->region.height=height;
443 iterator->region.x=x;
444 iterator->region.y=y;
445 iterator->pixel_wands=NewPixelWands(iterator->region.width);
446 iterator->y=0;
447 iterator->debug=IsEventLogging();
448 if (iterator->debug != MagickFalse)
449 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
450 iterator->signature=MagickWandSignature;
451 return(iterator);
452 }
453
454 /*
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 % %
457 % %
458 % %
459 % 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 %
460 % %
461 % %
462 % %
463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 %
465 % PixelGetCurrentIteratorRow() returns the current row as an array of pixel
466 % wands from the pixel iterator.
467 %
468 % The format of the PixelGetCurrentIteratorRow method is:
469 %
470 % PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
471 % size_t *number_wands)
472 %
473 % A description of each parameter follows:
474 %
475 % o iterator: the pixel iterator.
476 %
477 % o number_wands: the number of pixel wands.
478 %
479 */
PixelGetCurrentIteratorRow(PixelIterator * iterator,size_t * number_wands)480 WandExport PixelWand **PixelGetCurrentIteratorRow(PixelIterator *iterator,
481 size_t *number_wands)
482 {
483 const Quantum
484 *pixels;
485
486 ssize_t
487 x;
488
489 assert(iterator != (PixelIterator *) NULL);
490 assert(iterator->signature == MagickWandSignature);
491 if (iterator->debug != MagickFalse)
492 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
493 *number_wands=0;
494 iterator->active=MagickTrue;
495 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
496 iterator->region.y+iterator->y,iterator->region.width,1,
497 iterator->exception);
498 if (pixels == (const Quantum *) NULL)
499 return((PixelWand **) NULL);
500 for (x=0; x < (ssize_t) iterator->region.width; x++)
501 {
502 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
503 iterator->pixel_wands[x]);
504 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
505 }
506 *number_wands=iterator->region.width;
507 return(iterator->pixel_wands);
508 }
509
510 /*
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 % %
513 % %
514 % %
515 % 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 %
516 % %
517 % %
518 % %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 %
521 % PixelGetIteratorException() returns the severity, reason, and description of
522 % any error that occurs when using other methods in this API.
523 %
524 % The format of the PixelGetIteratorException method is:
525 %
526 % char *PixelGetIteratorException(const PixelIterator *iterator,
527 % ExceptionType *severity)
528 %
529 % A description of each parameter follows:
530 %
531 % o iterator: the pixel iterator.
532 %
533 % o severity: the severity of the error is returned here.
534 %
535 */
PixelGetIteratorException(const PixelIterator * iterator,ExceptionType * severity)536 WandExport char *PixelGetIteratorException(const PixelIterator *iterator,
537 ExceptionType *severity)
538 {
539 char
540 *description;
541
542 assert(iterator != (const PixelIterator *) NULL);
543 assert(iterator->signature == MagickWandSignature);
544 if (iterator->debug != MagickFalse)
545 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
546 assert(severity != (ExceptionType *) NULL);
547 *severity=iterator->exception->severity;
548 description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
549 sizeof(*description));
550 if (description == (char *) NULL)
551 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
552 iterator->name);
553 *description='\0';
554 if (iterator->exception->reason != (char *) NULL)
555 (void) CopyMagickString(description,GetLocaleExceptionMessage(
556 iterator->exception->severity,iterator->exception->reason),
557 MagickPathExtent);
558 if (iterator->exception->description != (char *) NULL)
559 {
560 (void) ConcatenateMagickString(description," (",MagickPathExtent);
561 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
562 iterator->exception->severity,iterator->exception->description),
563 MagickPathExtent);
564 (void) ConcatenateMagickString(description,")",MagickPathExtent);
565 }
566 return(description);
567 }
568
569 /*
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 % %
572 % %
573 % %
574 % P i x e l G e t E x c e p t i o n T y p e %
575 % %
576 % %
577 % %
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 %
580 % PixelGetIteratorExceptionType() the exception type associated with the
581 % iterator. If no exception has occurred, UndefinedExceptionType is returned.
582 %
583 % The format of the PixelGetIteratorExceptionType method is:
584 %
585 % ExceptionType PixelGetIteratorExceptionType(
586 % const PixelIterator *iterator)
587 %
588 % A description of each parameter follows:
589 %
590 % o iterator: the pixel iterator.
591 %
592 */
PixelGetIteratorExceptionType(const PixelIterator * iterator)593 WandExport ExceptionType PixelGetIteratorExceptionType(
594 const PixelIterator *iterator)
595 {
596 assert(iterator != (const PixelIterator *) NULL);
597 assert(iterator->signature == MagickWandSignature);
598 if (iterator->debug != MagickFalse)
599 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
600 return(iterator->exception->severity);
601 }
602
603 /*
604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605 % %
606 % %
607 % %
608 % P i x e l G e t I t e r a t o r R o w %
609 % %
610 % %
611 % %
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 %
614 % PixelGetIteratorRow() returns the current pixel iterator row.
615 %
616 % The format of the PixelGetIteratorRow method is:
617 %
618 % MagickBooleanType PixelGetIteratorRow(PixelIterator *iterator)
619 %
620 % A description of each parameter follows:
621 %
622 % o iterator: the pixel iterator.
623 %
624 */
PixelGetIteratorRow(PixelIterator * iterator)625 WandExport ssize_t PixelGetIteratorRow(PixelIterator *iterator)
626 {
627 assert(iterator != (const PixelIterator *) NULL);
628 assert(iterator->signature == MagickWandSignature);
629 if (iterator->debug != MagickFalse)
630 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
631 return(iterator->y);
632 }
633
634 /*
635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636 % %
637 % %
638 % %
639 % P i x e l G e t N e x t I t e r a t o r R o w %
640 % %
641 % %
642 % %
643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 %
645 % PixelGetNextIteratorRow() returns the next row as an array of pixel wands
646 % from the pixel iterator.
647 %
648 % The format of the PixelGetNextIteratorRow method is:
649 %
650 % PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
651 % size_t *number_wands)
652 %
653 % A description of each parameter follows:
654 %
655 % o iterator: the pixel iterator.
656 %
657 % o number_wands: the number of pixel wands.
658 %
659 */
PixelGetNextIteratorRow(PixelIterator * iterator,size_t * number_wands)660 WandExport PixelWand **PixelGetNextIteratorRow(PixelIterator *iterator,
661 size_t *number_wands)
662 {
663 const Quantum
664 *pixels;
665
666 ssize_t
667 x;
668
669 assert(iterator != (PixelIterator *) NULL);
670 assert(iterator->signature == MagickWandSignature);
671 if (iterator->debug != MagickFalse)
672 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
673 *number_wands=0;
674 if (iterator->active != MagickFalse)
675 iterator->y++;
676 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
677 return((PixelWand **) NULL);
678 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
679 iterator->region.y+iterator->y,iterator->region.width,1,
680 iterator->exception);
681 if (pixels == (const Quantum *) NULL)
682 return((PixelWand **) NULL);
683 for (x=0; x < (ssize_t) iterator->region.width; x++)
684 {
685 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
686 iterator->pixel_wands[x]);
687 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
688 }
689 *number_wands=iterator->region.width;
690 return(iterator->pixel_wands);
691 }
692
693 /*
694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695 % %
696 % %
697 % %
698 % 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 %
699 % %
700 % %
701 % %
702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703 %
704 % PixelGetPreviousIteratorRow() returns the previous row as an array of pixel
705 % wands from the pixel iterator.
706 %
707 % The format of the PixelGetPreviousIteratorRow method is:
708 %
709 % PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
710 % size_t *number_wands)
711 %
712 % A description of each parameter follows:
713 %
714 % o iterator: the pixel iterator.
715 %
716 % o number_wands: the number of pixel wands.
717 %
718 */
PixelGetPreviousIteratorRow(PixelIterator * iterator,size_t * number_wands)719 WandExport PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,
720 size_t *number_wands)
721 {
722 const Quantum
723 *pixels;
724
725 ssize_t
726 x;
727
728 assert(iterator != (PixelIterator *) NULL);
729 assert(iterator->signature == MagickWandSignature);
730 if (iterator->debug != MagickFalse)
731 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
732 *number_wands=0;
733 if (iterator->active != MagickFalse)
734 iterator->y--;
735 if (PixelSetIteratorRow(iterator,iterator->y) == MagickFalse)
736 return((PixelWand **) NULL);
737 pixels=GetCacheViewVirtualPixels(iterator->view,iterator->region.x,
738 iterator->region.y+iterator->y,iterator->region.width,1,
739 iterator->exception);
740 if (pixels == (const Quantum *) NULL)
741 return((PixelWand **) NULL);
742 for (x=0; x < (ssize_t) iterator->region.width; x++)
743 {
744 PixelSetQuantumPixel(GetCacheViewImage(iterator->view),pixels,
745 iterator->pixel_wands[x]);
746 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
747 }
748 *number_wands=iterator->region.width;
749 return(iterator->pixel_wands);
750 }
751
752 /*
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 % %
755 % %
756 % %
757 % P i x e l R e s e t I t e r a t o r %
758 % %
759 % %
760 % %
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 %
763 % PixelResetIterator() resets the pixel iterator. Use it in conjunction
764 % with PixelGetNextIteratorRow() to iterate over all the pixels in a pixel
765 % container.
766 %
767 % The format of the PixelResetIterator method is:
768 %
769 % void PixelResetIterator(PixelIterator *iterator)
770 %
771 % A description of each parameter follows:
772 %
773 % o iterator: the pixel iterator.
774 %
775 */
PixelResetIterator(PixelIterator * iterator)776 WandExport void PixelResetIterator(PixelIterator *iterator)
777 {
778 assert(iterator != (PixelIterator *) NULL);
779 assert(iterator->signature == MagickWandSignature);
780 if (iterator->debug != MagickFalse)
781 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
782 iterator->active=MagickFalse;
783 iterator->y=0;
784 }
785
786 /*
787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788 % %
789 % %
790 % %
791 % P i x e l S e t F i r s t I t e r a t o r R o w %
792 % %
793 % %
794 % %
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %
797 % PixelSetFirstIteratorRow() sets the pixel iterator to the first pixel row.
798 %
799 % The format of the PixelSetFirstIteratorRow method is:
800 %
801 % void PixelSetFirstIteratorRow(PixelIterator *iterator)
802 %
803 % A description of each parameter follows:
804 %
805 % o iterator: the magick iterator.
806 %
807 */
PixelSetFirstIteratorRow(PixelIterator * iterator)808 WandExport void PixelSetFirstIteratorRow(PixelIterator *iterator)
809 {
810 assert(iterator != (PixelIterator *) NULL);
811 assert(iterator->signature == MagickWandSignature);
812 if (iterator->debug != MagickFalse)
813 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
814 iterator->active=MagickFalse;
815 iterator->y=iterator->region.y;
816 }
817
818 /*
819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820 % %
821 % %
822 % %
823 % P i x e l S e t I t e r a t o r R o w %
824 % %
825 % %
826 % %
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828 %
829 % PixelSetIteratorRow() set the pixel iterator row.
830 %
831 % The format of the PixelSetIteratorRow method is:
832 %
833 % MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
834 % const ssize_t row)
835 %
836 % A description of each parameter follows:
837 %
838 % o iterator: the pixel iterator.
839 %
840 */
PixelSetIteratorRow(PixelIterator * iterator,const ssize_t row)841 WandExport MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,
842 const ssize_t row)
843 {
844 assert(iterator != (const PixelIterator *) NULL);
845 assert(iterator->signature == MagickWandSignature);
846 if (iterator->debug != MagickFalse)
847 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
848 if ((row < 0) || (row >= (ssize_t) iterator->region.height))
849 return(MagickFalse);
850 iterator->active=MagickTrue;
851 iterator->y=row;
852 return(MagickTrue);
853 }
854
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 % %
858 % %
859 % %
860 % P i x e l S e t L a s t I t e r a t o r R o w %
861 % %
862 % %
863 % %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 % PixelSetLastIteratorRow() sets the pixel iterator to the last pixel row.
867 %
868 % The format of the PixelSetLastIteratorRow method is:
869 %
870 % void PixelSetLastIteratorRow(PixelIterator *iterator)
871 %
872 % A description of each parameter follows:
873 %
874 % o iterator: the magick iterator.
875 %
876 */
PixelSetLastIteratorRow(PixelIterator * iterator)877 WandExport void PixelSetLastIteratorRow(PixelIterator *iterator)
878 {
879 assert(iterator != (PixelIterator *) NULL);
880 assert(iterator->signature == MagickWandSignature);
881 if (iterator->debug != MagickFalse)
882 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
883 iterator->active=MagickFalse;
884 iterator->y=(ssize_t) iterator->region.height-1;
885 }
886
887 /*
888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889 % %
890 % %
891 % %
892 % P i x e l S y n c I t e r a t o r %
893 % %
894 % %
895 % %
896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897 %
898 % PixelSyncIterator() syncs the pixel iterator.
899 %
900 % The format of the PixelSyncIterator method is:
901 %
902 % MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
903 %
904 % A description of each parameter follows:
905 %
906 % o iterator: the pixel iterator.
907 %
908 */
PixelSyncIterator(PixelIterator * iterator)909 WandExport MagickBooleanType PixelSyncIterator(PixelIterator *iterator)
910 {
911 MagickBooleanType
912 status;
913
914 Quantum
915 *magick_restrict pixels;
916
917 ssize_t
918 x;
919
920 assert(iterator != (const PixelIterator *) NULL);
921 assert(iterator->signature == MagickWandSignature);
922 if (iterator->debug != MagickFalse)
923 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",iterator->name);
924 status=SetCacheViewStorageClass(iterator->view,DirectClass,
925 iterator->exception);
926 if (status == MagickFalse)
927 return(MagickFalse);
928 pixels=GetCacheViewAuthenticPixels(iterator->view,iterator->region.x,
929 iterator->region.y+iterator->y,iterator->region.width,1,
930 iterator->exception);
931 if (pixels == (Quantum *) NULL)
932 return(MagickFalse);
933 for (x=0; x < (ssize_t) iterator->region.width; x++)
934 {
935 PixelGetQuantumPixel(GetCacheViewImage(iterator->view),
936 iterator->pixel_wands[x],pixels);
937 pixels+=GetPixelChannels(GetCacheViewImage(iterator->view));
938 }
939 if (SyncCacheViewAuthenticPixels(iterator->view,iterator->exception) == MagickFalse)
940 return(MagickFalse);
941 return(MagickTrue);
942 }
943