1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % DDDD EEEEE PPPP RRRR EEEEE CCCC AAA TTTTT EEEEE %
7 % D D E P P R R E C A A T E %
8 % D D EEE PPPPP RRRR EEE C AAAAA T EEE %
9 % D D E P R R E C A A T E %
10 % DDDD EEEEE P R R EEEEE CCCC A A T EEEEE %
11 % %
12 % %
13 % MagickWand Deprecated Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % October 2002 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39
40 /*
41 Include declarations.
42 */
43 #include "wand/studio.h"
44 #include "wand/MagickWand.h"
45 #include "wand/magick-wand-private.h"
46 #include "wand/wand.h"
47 #include "magick/monitor-private.h"
48 #include "magick/thread-private.h"
49
50 /*
51 Define declarations.
52 */
53 #define PixelViewId "PixelView"
54
55 /*
56 Typedef declarations.
57 */
58 struct _PixelView
59 {
60 size_t
61 id;
62
63 char
64 name[MaxTextExtent];
65
66 ExceptionInfo
67 *exception;
68
69 MagickWand
70 *wand;
71
72 CacheView
73 *view;
74
75 RectangleInfo
76 region;
77
78 size_t
79 number_threads;
80
81 PixelWand
82 ***pixel_wands;
83
84 MagickBooleanType
85 debug;
86
87 size_t
88 signature;
89 };
90
91 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
92 /*
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94 % %
95 % %
96 % %
97 + D r a w A l l o c a t e W a n d %
98 % %
99 % %
100 % %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 %
103 % DrawAllocateWand() allocates an initial drawing wand which is an opaque
104 % handle required by the remaining drawing methods.
105 %
106 % The format of the DrawAllocateWand method is:
107 %
108 % DrawingWand DrawAllocateWand(const DrawInfo *draw_info,Image *image)
109 %
110 % A description of each parameter follows:
111 %
112 % o draw_info: Initial drawing defaults. Set to NULL to use defaults.
113 %
114 % o image: the image to draw on.
115 %
116 */
DrawAllocateWand(const DrawInfo * draw_info,Image * image)117 WandExport DrawingWand *DrawAllocateWand(const DrawInfo *draw_info,Image *image)
118 {
119 return(AcquireDrawingWand(draw_info,image));
120 }
121
122 /*
123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124 % %
125 % %
126 % %
127 % M a g i c k A v e r a g e I m a g e s %
128 % %
129 % %
130 % %
131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 %
133 % MagickAverageImages() average a set of images.
134 %
135 % The format of the MagickAverageImages method is:
136 %
137 % MagickWand *MagickAverageImages(MagickWand *wand)
138 %
139 % A description of each parameter follows:
140 %
141 % o wand: the magick wand.
142 %
143 */
144
CloneMagickWandFromImages(const MagickWand * wand,Image * images)145 static MagickWand *CloneMagickWandFromImages(const MagickWand *wand,
146 Image *images)
147 {
148 MagickWand
149 *clone_wand;
150
151 assert(wand != (MagickWand *) NULL);
152 assert(wand->signature == WandSignature);
153 if (wand->debug != MagickFalse)
154 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
155 clone_wand=(MagickWand *) AcquireMagickMemory(sizeof(*clone_wand));
156 if (clone_wand == (MagickWand *) NULL)
157 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
158 images->filename);
159 (void) memset(clone_wand,0,sizeof(*clone_wand));
160 clone_wand->id=AcquireWandId();
161 (void) FormatLocaleString(clone_wand->name,MaxTextExtent,"%s-%.20g",
162 MagickWandId,(double) clone_wand->id);
163 clone_wand->exception=AcquireExceptionInfo();
164 InheritException(clone_wand->exception,wand->exception);
165 clone_wand->image_info=CloneImageInfo(wand->image_info);
166 clone_wand->quantize_info=CloneQuantizeInfo(wand->quantize_info);
167 clone_wand->images=images;
168 clone_wand->debug=IsEventLogging();
169 if (clone_wand->debug != MagickFalse)
170 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_wand->name);
171 clone_wand->signature=WandSignature;
172 return(clone_wand);
173 }
174
MagickAverageImages(MagickWand * wand)175 WandExport MagickWand *MagickAverageImages(MagickWand *wand)
176 {
177 Image
178 *average_image;
179
180 assert(wand != (MagickWand *) NULL);
181 assert(wand->signature == WandSignature);
182 if (wand->debug != MagickFalse)
183 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
184 if (wand->images == (Image *) NULL)
185 return((MagickWand *) NULL);
186 average_image=EvaluateImages(wand->images,MeanEvaluateOperator,
187 wand->exception);
188 if (average_image == (Image *) NULL)
189 return((MagickWand *) NULL);
190 return(CloneMagickWandFromImages(wand,average_image));
191 }
192
193 /*
194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195 % %
196 % %
197 % %
198 % C l o n e P i x e l V i e w %
199 % %
200 % %
201 % %
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203 %
204 % ClonePixelView() makes a copy of the specified pixel view.
205 %
206 % The format of the ClonePixelView method is:
207 %
208 % PixelView *ClonePixelView(const PixelView *pixel_view)
209 %
210 % A description of each parameter follows:
211 %
212 % o pixel_view: the pixel view.
213 %
214 */
ClonePixelView(const PixelView * pixel_view)215 WandExport PixelView *ClonePixelView(const PixelView *pixel_view)
216 {
217 PixelView
218 *clone_view;
219
220 ssize_t
221 i;
222
223 assert(pixel_view != (PixelView *) NULL);
224 assert(pixel_view->signature == WandSignature);
225 if (pixel_view->debug != MagickFalse)
226 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
227 clone_view=(PixelView *) AcquireMagickMemory(sizeof(*clone_view));
228 if (clone_view == (PixelView *) NULL)
229 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
230 pixel_view->name);
231 (void) memset(clone_view,0,sizeof(*clone_view));
232 clone_view->id=AcquireWandId();
233 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
234 PixelViewId,(double) clone_view->id);
235 clone_view->exception=AcquireExceptionInfo();
236 InheritException(clone_view->exception,pixel_view->exception);
237 clone_view->view=CloneCacheView(pixel_view->view);
238 clone_view->region=pixel_view->region;
239 clone_view->number_threads=pixel_view->number_threads;
240 for (i=0; i < (ssize_t) pixel_view->number_threads; i++)
241 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
242 pixel_view->pixel_wands[i],pixel_view->region.width);
243 clone_view->debug=pixel_view->debug;
244 if (clone_view->debug != MagickFalse)
245 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
246 clone_view->signature=WandSignature;
247 return(clone_view);
248 }
249
250 /*
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % %
253 % %
254 % %
255 % D e s t r o y P i x e l V i e w %
256 % %
257 % %
258 % %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 %
261 % DestroyPixelView() deallocates memory associated with a pixel view.
262 %
263 % The format of the DestroyPixelView method is:
264 %
265 % PixelView *DestroyPixelView(PixelView *pixel_view,
266 % const size_t number_wands,const size_t number_threads)
267 %
268 % A description of each parameter follows:
269 %
270 % o pixel_view: the pixel view.
271 %
272 % o number_wand: the number of pixel wands.
273 %
274 % o number_threads: number of threads.
275 %
276 */
277
DestroyPixelsThreadSet(PixelWand *** pixel_wands,const size_t number_wands,const size_t number_threads)278 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
279 const size_t number_wands,const size_t number_threads)
280 {
281 ssize_t
282 i;
283
284 assert(pixel_wands != (PixelWand ***) NULL);
285 for (i=0; i < (ssize_t) number_threads; i++)
286 if (pixel_wands[i] != (PixelWand **) NULL)
287 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
288 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
289 return(pixel_wands);
290 }
291
DestroyPixelView(PixelView * pixel_view)292 WandExport PixelView *DestroyPixelView(PixelView *pixel_view)
293 {
294 assert(pixel_view != (PixelView *) NULL);
295 assert(pixel_view->signature == WandSignature);
296 pixel_view->pixel_wands=DestroyPixelsThreadSet(pixel_view->pixel_wands,
297 pixel_view->region.width,pixel_view->number_threads);
298 pixel_view->view=DestroyCacheView(pixel_view->view);
299 pixel_view->exception=DestroyExceptionInfo(pixel_view->exception);
300 pixel_view->signature=(~WandSignature);
301 RelinquishWandId(pixel_view->id);
302 pixel_view=(PixelView *) RelinquishMagickMemory(pixel_view);
303 return(pixel_view);
304 }
305
306 /*
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308 % %
309 % %
310 % %
311 % D u p l e x T r a n s f e r P i x e l V i e w I t e r a t o r %
312 % %
313 % %
314 % %
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 %
317 % DuplexTransferPixelViewIterator() iterates over three pixel views in
318 % parallel and calls your transfer method for each scanline of the view. The
319 % source and duplex pixel region is not confined to the image canvas-- that is
320 % you can include negative offsets or widths or heights that exceed the image
321 % dimension. However, the destination pixel view is confined to the image
322 % canvas-- that is no negative offsets or widths or heights that exceed the
323 % image dimension are permitted.
324 %
325 % Use this pragma:
326 %
327 % #pragma omp critical
328 %
329 % to define a section of code in your callback transfer method that must be
330 % executed by a single thread at a time.
331 %
332 % The format of the DuplexTransferPixelViewIterator method is:
333 %
334 % MagickBooleanType DuplexTransferPixelViewIterator(PixelView *source,
335 % PixelView *duplex,PixelView *destination,
336 % DuplexTransferPixelViewMethod transfer,void *context)
337 %
338 % A description of each parameter follows:
339 %
340 % o source: the source pixel view.
341 %
342 % o duplex: the duplex pixel view.
343 %
344 % o destination: the destination pixel view.
345 %
346 % o transfer: the transfer callback method.
347 %
348 % o context: the user defined context.
349 %
350 */
DuplexTransferPixelViewIterator(PixelView * source,PixelView * duplex,PixelView * destination,DuplexTransferPixelViewMethod transfer,void * context)351 WandExport MagickBooleanType DuplexTransferPixelViewIterator(
352 PixelView *source,PixelView *duplex,PixelView *destination,
353 DuplexTransferPixelViewMethod transfer,void *context)
354 {
355 #define DuplexTransferPixelViewTag "PixelView/DuplexTransfer"
356
357 ExceptionInfo
358 *exception;
359
360 Image
361 *destination_image,
362 *duplex_image,
363 *source_image;
364
365 MagickBooleanType
366 status;
367
368 MagickOffsetType
369 progress;
370
371 ssize_t
372 y;
373
374 assert(source != (PixelView *) NULL);
375 assert(source->signature == WandSignature);
376 if (transfer == (DuplexTransferPixelViewMethod) NULL)
377 return(MagickFalse);
378 source_image=source->wand->images;
379 duplex_image=duplex->wand->images;
380 destination_image=destination->wand->images;
381 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
382 return(MagickFalse);
383 status=MagickTrue;
384 progress=0;
385 exception=destination->exception;
386 #if defined(MAGICKCORE_OPENMP_SUPPORT)
387 #pragma omp parallel for schedule(static) shared(progress,status)
388 #endif
389 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
390 {
391 const int
392 id = GetOpenMPThreadId();
393
394 MagickBooleanType
395 sync;
396
397 const IndexPacket
398 *magick_restrict duplex_indexes,
399 *magick_restrict indexes;
400
401 const PixelPacket
402 *magick_restrict duplex_pixels,
403 *magick_restrict pixels;
404
405 IndexPacket
406 *magick_restrict destination_indexes;
407
408 ssize_t
409 x;
410
411 PixelPacket
412 *magick_restrict destination_pixels;
413
414 if (status == MagickFalse)
415 continue;
416 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
417 source->region.width,1,source->exception);
418 if (pixels == (const PixelPacket *) NULL)
419 {
420 status=MagickFalse;
421 continue;
422 }
423 indexes=GetCacheViewVirtualIndexQueue(source->view);
424 for (x=0; x < (ssize_t) source->region.width; x++)
425 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
426 if (source_image->colorspace == CMYKColorspace)
427 for (x=0; x < (ssize_t) source->region.width; x++)
428 PixelSetBlackQuantum(source->pixel_wands[id][x],
429 GetPixelIndex(indexes+x));
430 if (source_image->storage_class == PseudoClass)
431 for (x=0; x < (ssize_t) source->region.width; x++)
432 PixelSetIndex(source->pixel_wands[id][x],
433 GetPixelIndex(indexes+x));
434 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->region.x,y,
435 duplex->region.width,1,duplex->exception);
436 if (duplex_pixels == (const PixelPacket *) NULL)
437 {
438 status=MagickFalse;
439 continue;
440 }
441 duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
442 for (x=0; x < (ssize_t) duplex->region.width; x++)
443 PixelSetQuantumColor(duplex->pixel_wands[id][x],duplex_pixels+x);
444 if (duplex_image->colorspace == CMYKColorspace)
445 for (x=0; x < (ssize_t) duplex->region.width; x++)
446 PixelSetBlackQuantum(duplex->pixel_wands[id][x],
447 GetPixelIndex(duplex_indexes+x));
448 if (duplex_image->storage_class == PseudoClass)
449 for (x=0; x < (ssize_t) duplex->region.width; x++)
450 PixelSetIndex(duplex->pixel_wands[id][x],
451 GetPixelIndex(duplex_indexes+x));
452 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
453 destination->region.x,y,destination->region.width,1,exception);
454 if (destination_pixels == (PixelPacket *) NULL)
455 {
456 status=MagickFalse;
457 continue;
458 }
459 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
460 for (x=0; x < (ssize_t) destination->region.width; x++)
461 PixelSetQuantumColor(destination->pixel_wands[id][x],
462 destination_pixels+x);
463 if (destination_image->colorspace == CMYKColorspace)
464 for (x=0; x < (ssize_t) destination->region.width; x++)
465 PixelSetBlackQuantum(destination->pixel_wands[id][x],
466 GetPixelIndex(destination_indexes+x));
467 if (destination_image->storage_class == PseudoClass)
468 for (x=0; x < (ssize_t) destination->region.width; x++)
469 PixelSetIndex(destination->pixel_wands[id][x],
470 GetPixelIndex(destination_indexes+x));
471 if (transfer(source,duplex,destination,context) == MagickFalse)
472 status=MagickFalse;
473 for (x=0; x < (ssize_t) destination->region.width; x++)
474 PixelGetQuantumColor(destination->pixel_wands[id][x],
475 destination_pixels+x);
476 if (destination_image->colorspace == CMYKColorspace)
477 for (x=0; x < (ssize_t) destination->region.width; x++)
478 SetPixelIndex(destination_indexes+x,PixelGetBlackQuantum(
479 destination->pixel_wands[id][x]));
480 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
481 if (sync == MagickFalse)
482 {
483 InheritException(destination->exception,GetCacheViewException(
484 source->view));
485 status=MagickFalse;
486 }
487 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
488 {
489 MagickBooleanType
490 proceed;
491
492
493 #if defined(MAGICKCORE_OPENMP_SUPPORT)
494 #pragma omp atomic
495 #endif
496 progress++;
497 proceed=SetImageProgress(source_image,DuplexTransferPixelViewTag,
498 progress,source->region.height);
499 if (proceed == MagickFalse)
500 status=MagickFalse;
501 }
502 }
503 return(status);
504 }
505
506 /*
507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 % %
509 % %
510 % %
511 % G e t P i x e l V i e w E x c e p t i o n %
512 % %
513 % %
514 % %
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516 %
517 % GetPixelViewException() returns the severity, reason, and description of any
518 % error that occurs when utilizing a pixel view.
519 %
520 % The format of the GetPixelViewException method is:
521 %
522 % char *GetPixelViewException(const PixelWand *pixel_view,
523 % ExceptionType *severity)
524 %
525 % A description of each parameter follows:
526 %
527 % o pixel_view: the pixel pixel_view.
528 %
529 % o severity: the severity of the error is returned here.
530 %
531 */
GetPixelViewException(const PixelView * pixel_view,ExceptionType * severity)532 WandExport char *GetPixelViewException(const PixelView *pixel_view,
533 ExceptionType *severity)
534 {
535 char
536 *description;
537
538 assert(pixel_view != (const PixelView *) NULL);
539 assert(pixel_view->signature == WandSignature);
540 if (pixel_view->debug != MagickFalse)
541 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
542 assert(severity != (ExceptionType *) NULL);
543 *severity=pixel_view->exception->severity;
544 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
545 sizeof(*description));
546 if (description == (char *) NULL)
547 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
548 pixel_view->name);
549 *description='\0';
550 if (pixel_view->exception->reason != (char *) NULL)
551 (void) CopyMagickString(description,GetLocaleExceptionMessage(
552 pixel_view->exception->severity,pixel_view->exception->reason),
553 MaxTextExtent);
554 if (pixel_view->exception->description != (char *) NULL)
555 {
556 (void) ConcatenateMagickString(description," (",MaxTextExtent);
557 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
558 pixel_view->exception->severity,pixel_view->exception->description),
559 MaxTextExtent);
560 (void) ConcatenateMagickString(description,")",MaxTextExtent);
561 }
562 return(description);
563 }
564
565 /*
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 % %
568 % %
569 % %
570 % G e t P i x e l V i e w H e i g h t %
571 % %
572 % %
573 % %
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 %
576 % GetPixelViewHeight() returns the pixel view height.
577 %
578 % The format of the GetPixelViewHeight method is:
579 %
580 % size_t GetPixelViewHeight(const PixelView *pixel_view)
581 %
582 % A description of each parameter follows:
583 %
584 % o pixel_view: the pixel view.
585 %
586 */
GetPixelViewHeight(const PixelView * pixel_view)587 WandExport size_t GetPixelViewHeight(const PixelView *pixel_view)
588 {
589 assert(pixel_view != (PixelView *) NULL);
590 assert(pixel_view->signature == WandSignature);
591 return(pixel_view->region.height);
592 }
593
594 /*
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 % %
597 % %
598 % %
599 % G e t P i x e l V i e w I t e r a t o r %
600 % %
601 % %
602 % %
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 %
605 % GetPixelViewIterator() iterates over the pixel view in parallel and calls
606 % your get method for each scanline of the view. The pixel region is
607 % not confined to the image canvas-- that is you can include negative offsets
608 % or widths or heights that exceed the image dimension. Any updates to
609 % the pixels in your callback are ignored.
610 %
611 % Use this pragma:
612 %
613 % #pragma omp critical
614 %
615 % to define a section of code in your callback get method that must be
616 % executed by a single thread at a time.
617 %
618 % The format of the GetPixelViewIterator method is:
619 %
620 % MagickBooleanType GetPixelViewIterator(PixelView *source,
621 % GetPixelViewMethod get,void *context)
622 %
623 % A description of each parameter follows:
624 %
625 % o source: the source pixel view.
626 %
627 % o get: the get callback method.
628 %
629 % o context: the user defined context.
630 %
631 */
GetPixelViewIterator(PixelView * source,GetPixelViewMethod get,void * context)632 WandExport MagickBooleanType GetPixelViewIterator(PixelView *source,
633 GetPixelViewMethod get,void *context)
634 {
635 #define GetPixelViewTag "PixelView/Get"
636
637 Image
638 *source_image;
639
640 MagickBooleanType
641 status;
642
643 MagickOffsetType
644 progress;
645
646 ssize_t
647 y;
648
649 assert(source != (PixelView *) NULL);
650 assert(source->signature == WandSignature);
651 if (get == (GetPixelViewMethod) NULL)
652 return(MagickFalse);
653 source_image=source->wand->images;
654 status=MagickTrue;
655 progress=0;
656 #if defined(MAGICKCORE_OPENMP_SUPPORT)
657 #pragma omp parallel for schedule(static) shared(progress,status)
658 #endif
659 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
660 {
661 const int
662 id = GetOpenMPThreadId();
663
664 const IndexPacket
665 *indexes;
666
667 const PixelPacket
668 *pixels;
669
670 ssize_t
671 x;
672
673 if (status == MagickFalse)
674 continue;
675 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
676 source->region.width,1,source->exception);
677 if (pixels == (const PixelPacket *) NULL)
678 {
679 status=MagickFalse;
680 continue;
681 }
682 indexes=GetCacheViewVirtualIndexQueue(source->view);
683 for (x=0; x < (ssize_t) source->region.width; x++)
684 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
685 if (source_image->colorspace == CMYKColorspace)
686 for (x=0; x < (ssize_t) source->region.width; x++)
687 PixelSetBlackQuantum(source->pixel_wands[id][x],
688 GetPixelIndex(indexes+x));
689 if (source_image->storage_class == PseudoClass)
690 for (x=0; x < (ssize_t) source->region.width; x++)
691 PixelSetIndex(source->pixel_wands[id][x],
692 GetPixelIndex(indexes+x));
693 if (get(source,context) == MagickFalse)
694 status=MagickFalse;
695 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
696 {
697 MagickBooleanType
698 proceed;
699
700 #if defined(MAGICKCORE_OPENMP_SUPPORT)
701 #pragma omp atomic
702 #endif
703 progress++;
704 proceed=SetImageProgress(source_image,GetPixelViewTag,progress,
705 source->region.height);
706 if (proceed == MagickFalse)
707 status=MagickFalse;
708 }
709 }
710 return(status);
711 }
712
713 /*
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 % %
716 % %
717 % %
718 % G e t P i x e l V i e w P i x e l s %
719 % %
720 % %
721 % %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 %
724 % GetPixelViewPixels() returns the pixel view pixel_wands.
725 %
726 % The format of the GetPixelViewPixels method is:
727 %
728 % PixelWand *GetPixelViewPixels(const PixelView *pixel_view)
729 %
730 % A description of each parameter follows:
731 %
732 % o pixel_view: the pixel view.
733 %
734 */
GetPixelViewPixels(const PixelView * pixel_view)735 WandExport PixelWand **GetPixelViewPixels(const PixelView *pixel_view)
736 {
737 const int
738 id = GetOpenMPThreadId();
739
740 assert(pixel_view != (PixelView *) NULL);
741 assert(pixel_view->signature == WandSignature);
742 return(pixel_view->pixel_wands[id]);
743 }
744
745 /*
746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747 % %
748 % %
749 % %
750 % G e t P i x e l V i e w W a n d %
751 % %
752 % %
753 % %
754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755 %
756 % GetPixelViewWand() returns the magick wand associated with the pixel view.
757 %
758 % The format of the GetPixelViewWand method is:
759 %
760 % MagickWand *GetPixelViewWand(const PixelView *pixel_view)
761 %
762 % A description of each parameter follows:
763 %
764 % o pixel_view: the pixel view.
765 %
766 */
GetPixelViewWand(const PixelView * pixel_view)767 WandExport MagickWand *GetPixelViewWand(const PixelView *pixel_view)
768 {
769 assert(pixel_view != (PixelView *) NULL);
770 assert(pixel_view->signature == WandSignature);
771 return(pixel_view->wand);
772 }
773
774 /*
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776 % %
777 % %
778 % %
779 % G e t P i x e l V i e w W i d t h %
780 % %
781 % %
782 % %
783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 %
785 % GetPixelViewWidth() returns the pixel view width.
786 %
787 % The format of the GetPixelViewWidth method is:
788 %
789 % size_t GetPixelViewWidth(const PixelView *pixel_view)
790 %
791 % A description of each parameter follows:
792 %
793 % o pixel_view: the pixel view.
794 %
795 */
GetPixelViewWidth(const PixelView * pixel_view)796 WandExport size_t GetPixelViewWidth(const PixelView *pixel_view)
797 {
798 assert(pixel_view != (PixelView *) NULL);
799 assert(pixel_view->signature == WandSignature);
800 return(pixel_view->region.width);
801 }
802
803 /*
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 % %
806 % %
807 % %
808 % G e t P i x e l V i e w X %
809 % %
810 % %
811 % %
812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813 %
814 % GetPixelViewX() returns the pixel view x offset.
815 %
816 % The format of the GetPixelViewX method is:
817 %
818 % ssize_t GetPixelViewX(const PixelView *pixel_view)
819 %
820 % A description of each parameter follows:
821 %
822 % o pixel_view: the pixel view.
823 %
824 */
GetPixelViewX(const PixelView * pixel_view)825 WandExport ssize_t GetPixelViewX(const PixelView *pixel_view)
826 {
827 assert(pixel_view != (PixelView *) NULL);
828 assert(pixel_view->signature == WandSignature);
829 return(pixel_view->region.x);
830 }
831
832 /*
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 % %
835 % %
836 % %
837 % G e t P i x e l V i e w Y %
838 % %
839 % %
840 % %
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %
843 % GetPixelViewY() returns the pixel view y offset.
844 %
845 % The format of the GetPixelViewY method is:
846 %
847 % ssize_t GetPixelViewY(const PixelView *pixel_view)
848 %
849 % A description of each parameter follows:
850 %
851 % o pixel_view: the pixel view.
852 %
853 */
GetPixelViewY(const PixelView * pixel_view)854 WandExport ssize_t GetPixelViewY(const PixelView *pixel_view)
855 {
856 assert(pixel_view != (PixelView *) NULL);
857 assert(pixel_view->signature == WandSignature);
858 return(pixel_view->region.y);
859 }
860
861 /*
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 % %
864 % %
865 % %
866 % I s P i x e l V i e w %
867 % %
868 % %
869 % %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %
872 % IsPixelView() returns MagickTrue if the parameter is verified as a pixel
873 % view container.
874 %
875 % The format of the IsPixelView method is:
876 %
877 % MagickBooleanType IsPixelView(const PixelView *pixel_view)
878 %
879 % A description of each parameter follows:
880 %
881 % o pixel_view: the pixel view.
882 %
883 */
IsPixelView(const PixelView * pixel_view)884 WandExport MagickBooleanType IsPixelView(const PixelView *pixel_view)
885 {
886 size_t
887 length;
888
889 if (pixel_view == (const PixelView *) NULL)
890 return(MagickFalse);
891 if (pixel_view->signature != WandSignature)
892 return(MagickFalse);
893 length=strlen(PixelViewId);
894 if (LocaleNCompare(pixel_view->name,PixelViewId,length) != 0)
895 return(MagickFalse);
896 return(MagickTrue);
897 }
898
899 /*
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % %
902 % %
903 % %
904 % M a g i c k C l i p P a t h I m a g e %
905 % %
906 % %
907 % %
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 %
910 % MagickClipPathImage() clips along the named paths from the 8BIM profile, if
911 % present. Later operations take effect inside the path. Id may be a number
912 % if preceded with #, to work on a numbered path, e.g., "#1" to use the first
913 % path.
914 %
915 % The format of the MagickClipPathImage method is:
916 %
917 % MagickBooleanType MagickClipPathImage(MagickWand *wand,
918 % const char *pathname,const MagickBooleanType inside)
919 %
920 % A description of each parameter follows:
921 %
922 % o wand: the magick wand.
923 %
924 % o pathname: name of clipping path resource. If name is preceded by #, use
925 % clipping path numbered by name.
926 %
927 % o inside: if non-zero, later operations take effect inside clipping path.
928 % Otherwise later operations take effect outside clipping path.
929 %
930 */
MagickClipPathImage(MagickWand * wand,const char * pathname,const MagickBooleanType inside)931 WandExport MagickBooleanType MagickClipPathImage(MagickWand *wand,
932 const char *pathname,const MagickBooleanType inside)
933 {
934 return(MagickClipImagePath(wand,pathname,inside));
935 }
936 /*
937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
938 % %
939 % %
940 % %
941 % D r a w G e t F i l l A l p h a %
942 % %
943 % %
944 % %
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 %
947 % DrawGetFillAlpha() returns the alpha used when drawing using the fill
948 % color or fill texture. Fully opaque is 1.0.
949 %
950 % The format of the DrawGetFillAlpha method is:
951 %
952 % double DrawGetFillAlpha(const DrawingWand *wand)
953 %
954 % A description of each parameter follows:
955 %
956 % o wand: the drawing wand.
957 %
958 */
DrawGetFillAlpha(const DrawingWand * wand)959 WandExport double DrawGetFillAlpha(const DrawingWand *wand)
960 {
961 return(DrawGetFillOpacity(wand));
962 }
963
964 /*
965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 % %
967 % %
968 % %
969 % D r a w G e t S t r o k e A l p h a %
970 % %
971 % %
972 % %
973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974 %
975 % DrawGetStrokeAlpha() returns the alpha of stroked object outlines.
976 %
977 % The format of the DrawGetStrokeAlpha method is:
978 %
979 % double DrawGetStrokeAlpha(const DrawingWand *wand)
980 %
981 % A description of each parameter follows:
982 %
983 % o wand: the drawing wand.
984 */
DrawGetStrokeAlpha(const DrawingWand * wand)985 WandExport double DrawGetStrokeAlpha(const DrawingWand *wand)
986 {
987 return(DrawGetStrokeOpacity(wand));
988 }
989
990 /*
991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 % %
993 % %
994 % %
995 % D r a w P e e k G r a p h i c W a n d %
996 % %
997 % %
998 % %
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 %
1001 % DrawPeekGraphicWand() returns the current drawing wand.
1002 %
1003 % The format of the PeekDrawingWand method is:
1004 %
1005 % DrawInfo *DrawPeekGraphicWand(const DrawingWand *wand)
1006 %
1007 % A description of each parameter follows:
1008 %
1009 % o wand: the drawing wand.
1010 %
1011 */
DrawPeekGraphicWand(const DrawingWand * wand)1012 WandExport DrawInfo *DrawPeekGraphicWand(const DrawingWand *wand)
1013 {
1014 return(PeekDrawingWand(wand));
1015 }
1016
1017 /*
1018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 % %
1020 % %
1021 % %
1022 % D r a w P o p G r a p h i c C o n t e x t %
1023 % %
1024 % %
1025 % %
1026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1027 %
1028 % DrawPopGraphicContext() destroys the current drawing wand and returns to the
1029 % previously pushed drawing wand. Multiple drawing wands may exist. It is an
1030 % error to attempt to pop more drawing wands than have been pushed, and it is
1031 % proper form to pop all drawing wands which have been pushed.
1032 %
1033 % The format of the DrawPopGraphicContext method is:
1034 %
1035 % MagickBooleanType DrawPopGraphicContext(DrawingWand *wand)
1036 %
1037 % A description of each parameter follows:
1038 %
1039 % o wand: the drawing wand.
1040 %
1041 */
DrawPopGraphicContext(DrawingWand * wand)1042 WandExport void DrawPopGraphicContext(DrawingWand *wand)
1043 {
1044 (void) PopDrawingWand(wand);
1045 }
1046
1047 /*
1048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1049 % %
1050 % %
1051 % %
1052 % D r a w P u s h G r a p h i c C o n t e x t %
1053 % %
1054 % %
1055 % %
1056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1057 %
1058 % DrawPushGraphicContext() clones the current drawing wand to create a new
1059 % drawing wand. The original drawing wand(s) may be returned to by
1060 % invoking PopDrawingWand(). The drawing wands are stored on a drawing wand
1061 % stack. For every Pop there must have already been an equivalent Push.
1062 %
1063 % The format of the DrawPushGraphicContext method is:
1064 %
1065 % MagickBooleanType DrawPushGraphicContext(DrawingWand *wand)
1066 %
1067 % A description of each parameter follows:
1068 %
1069 % o wand: the drawing wand.
1070 %
1071 */
DrawPushGraphicContext(DrawingWand * wand)1072 WandExport void DrawPushGraphicContext(DrawingWand *wand)
1073 {
1074 (void) PushDrawingWand(wand);
1075 }
1076
1077 /*
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 % %
1080 % %
1081 % %
1082 % D r a w S e t F i l l A l p h a %
1083 % %
1084 % %
1085 % %
1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1087 %
1088 % DrawSetFillAlpha() sets the alpha to use when drawing using the fill
1089 % color or fill texture. Fully opaque is 1.0.
1090 %
1091 % The format of the DrawSetFillAlpha method is:
1092 %
1093 % void DrawSetFillAlpha(DrawingWand *wand,const double fill_alpha)
1094 %
1095 % A description of each parameter follows:
1096 %
1097 % o wand: the drawing wand.
1098 %
1099 % o fill_alpha: fill alpha
1100 %
1101 */
DrawSetFillAlpha(DrawingWand * wand,const double fill_alpha)1102 WandExport void DrawSetFillAlpha(DrawingWand *wand,const double fill_alpha)
1103 {
1104 DrawSetFillOpacity(wand,fill_alpha);
1105 }
1106
1107 /*
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % %
1110 % %
1111 % %
1112 % D r a w S e t S t r o k e A l p h a %
1113 % %
1114 % %
1115 % %
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %
1118 % DrawSetStrokeAlpha() specifies the alpha of stroked object outlines.
1119 %
1120 % The format of the DrawSetStrokeAlpha method is:
1121 %
1122 % void DrawSetStrokeAlpha(DrawingWand *wand,const double stroke_alpha)
1123 %
1124 % A description of each parameter follows:
1125 %
1126 % o wand: the drawing wand.
1127 %
1128 % o stroke_alpha: stroke alpha. The value 1.0 is opaque.
1129 %
1130 */
DrawSetStrokeAlpha(DrawingWand * wand,const double stroke_alpha)1131 WandExport void DrawSetStrokeAlpha(DrawingWand *wand,const double stroke_alpha)
1132 {
1133 DrawSetStrokeOpacity(wand,stroke_alpha);
1134 }
1135
1136 /*
1137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138 % %
1139 % %
1140 % %
1141 % M a g i c k C o l o r F l o o d f i l l I m a g e %
1142 % %
1143 % %
1144 % %
1145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1146 %
1147 % MagickColorFloodfillImage() changes the color value of any pixel that matches
1148 % target and is an immediate neighbor. If the method FillToBorderMethod is
1149 % specified, the color value is changed for any neighbor pixel that does not
1150 % match the bordercolor member of image.
1151 %
1152 % The format of the MagickColorFloodfillImage method is:
1153 %
1154 % MagickBooleanType MagickColorFloodfillImage(MagickWand *wand,
1155 % const PixelWand *fill,const double fuzz,const PixelWand *bordercolor,
1156 % const ssize_t x,const ssize_t y)
1157 %
1158 % A description of each parameter follows:
1159 %
1160 % o wand: the magick wand.
1161 %
1162 % o fill: the floodfill color pixel wand.
1163 %
1164 % o fuzz: By default target must match a particular pixel color
1165 % exactly. However, in many cases two colors may differ by a small amount.
1166 % The fuzz member of image defines how much tolerance is acceptable to
1167 % consider two colors as the same. For example, set fuzz to 10 and the
1168 % color red at intensities of 100 and 102 respectively are now interpreted
1169 % as the same color for the purposes of the floodfill.
1170 %
1171 % o bordercolor: the border color pixel wand.
1172 %
1173 % o x,y: the starting location of the operation.
1174 %
1175 */
MagickColorFloodfillImage(MagickWand * wand,const PixelWand * fill,const double fuzz,const PixelWand * bordercolor,const ssize_t x,const ssize_t y)1176 WandExport MagickBooleanType MagickColorFloodfillImage(MagickWand *wand,
1177 const PixelWand *fill,const double fuzz,const PixelWand *bordercolor,
1178 const ssize_t x,const ssize_t y)
1179 {
1180 DrawInfo
1181 *draw_info;
1182
1183 MagickBooleanType
1184 status;
1185
1186 PixelPacket
1187 target;
1188
1189 assert(wand != (MagickWand *) NULL);
1190 assert(wand->signature == WandSignature);
1191 if (wand->debug != MagickFalse)
1192 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1193 if (wand->images == (Image *) NULL)
1194 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1195 draw_info=CloneDrawInfo(wand->image_info,(DrawInfo *) NULL);
1196 PixelGetQuantumColor(fill,&draw_info->fill);
1197 (void) GetOneVirtualPixel(wand->images,x % wand->images->columns,
1198 y % wand->images->rows,&target,wand->exception);
1199 if (bordercolor != (PixelWand *) NULL)
1200 PixelGetQuantumColor(bordercolor,&target);
1201 wand->images->fuzz=fuzz;
1202 status=ColorFloodfillImage(wand->images,draw_info,target,x,y,
1203 bordercolor != (PixelWand *) NULL ? FillToBorderMethod : FloodfillMethod);
1204 if (status == MagickFalse)
1205 InheritException(wand->exception,&wand->images->exception);
1206 draw_info=DestroyDrawInfo(draw_info);
1207 return(status);
1208 }
1209
1210 /*
1211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1212 % %
1213 % %
1214 % %
1215 % M a g i c k D e s c r i b e I m a g e %
1216 % %
1217 % %
1218 % %
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 %
1221 % MagickDescribeImage() identifies an image by printing its attributes to the
1222 % file. Attributes include the image width, height, size, and others.
1223 %
1224 % The format of the MagickDescribeImage method is:
1225 %
1226 % const char *MagickDescribeImage(MagickWand *wand)
1227 %
1228 % A description of each parameter follows:
1229 %
1230 % o wand: the magick wand.
1231 %
1232 */
MagickDescribeImage(MagickWand * wand)1233 WandExport char *MagickDescribeImage(MagickWand *wand)
1234 {
1235 return(MagickIdentifyImage(wand));
1236 }
1237
1238 /*
1239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1240 % %
1241 % %
1242 % %
1243 % M a g i c k F l a t t e n I m a g e s %
1244 % %
1245 % %
1246 % %
1247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1248 %
1249 % MagickFlattenImages() merges a sequence of images. This useful for
1250 % combining Photoshop layers into a single image.
1251 %
1252 % The format of the MagickFlattenImages method is:
1253 %
1254 % MagickWand *MagickFlattenImages(MagickWand *wand)
1255 %
1256 % A description of each parameter follows:
1257 %
1258 % o wand: the magick wand.
1259 %
1260 */
MagickFlattenImages(MagickWand * wand)1261 WandExport MagickWand *MagickFlattenImages(MagickWand *wand)
1262 {
1263 Image
1264 *flatten_image;
1265
1266 assert(wand != (MagickWand *) NULL);
1267 assert(wand->signature == WandSignature);
1268 if (wand->debug != MagickFalse)
1269 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1270 if (wand->images == (Image *) NULL)
1271 return((MagickWand *) NULL);
1272 flatten_image=FlattenImages(wand->images,wand->exception);
1273 if (flatten_image == (Image *) NULL)
1274 return((MagickWand *) NULL);
1275 return(CloneMagickWandFromImages(wand,flatten_image));
1276 }
1277
1278 /*
1279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1280 % %
1281 % %
1282 % %
1283 % M a g i c k G e t I m a g e A t t r i b u t e %
1284 % %
1285 % %
1286 % %
1287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1288 %
1289 % MagickGetImageAttribute() returns a value associated with the specified
1290 % property. Use MagickRelinquishMemory() to free the value when you are
1291 % finished with it.
1292 %
1293 % The format of the MagickGetImageAttribute method is:
1294 %
1295 % char *MagickGetImageAttribute(MagickWand *wand,const char *property)
1296 %
1297 % A description of each parameter follows:
1298 %
1299 % o wand: the magick wand.
1300 %
1301 % o property: the property.
1302 %
1303 */
MagickGetImageAttribute(MagickWand * wand,const char * property)1304 WandExport char *MagickGetImageAttribute(MagickWand *wand,const char *property)
1305 {
1306 return(MagickGetImageProperty(wand,property));
1307 }
1308
1309 /*
1310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1311 % %
1312 % %
1313 % %
1314 + M a g i c k G e t I m a g e I n d e x %
1315 % %
1316 % %
1317 % %
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 %
1320 % MagickGetImageIndex() returns the index of the current image.
1321 %
1322 % The format of the MagickGetImageIndex method is:
1323 %
1324 % ssize_t MagickGetImageIndex(MagickWand *wand)
1325 %
1326 % A description of each parameter follows:
1327 %
1328 % o wand: the magick wand.
1329 %
1330 */
MagickGetImageIndex(MagickWand * wand)1331 WandExport ssize_t MagickGetImageIndex(MagickWand *wand)
1332 {
1333 return(MagickGetIteratorIndex(wand));
1334 }
1335
1336 /*
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1338 % %
1339 % %
1340 % %
1341 + M a g i c k G e t I m a g e C h a n n e l E x t r e m a %
1342 % %
1343 % %
1344 % %
1345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1346 %
1347 % MagickGetImageChannelExtrema() gets the extrema for one or more image
1348 % channels.
1349 %
1350 % The format of the MagickGetImageChannelExtrema method is:
1351 %
1352 % MagickBooleanType MagickGetImageChannelExtrema(MagickWand *wand,
1353 % const ChannelType channel,size_t *minima,size_t *maxima)
1354 %
1355 % A description of each parameter follows:
1356 %
1357 % o wand: the magick wand.
1358 %
1359 % o channel: the image channel(s).
1360 %
1361 % o minima: The minimum pixel value for the specified channel(s).
1362 %
1363 % o maxima: The maximum pixel value for the specified channel(s).
1364 %
1365 */
MagickGetImageChannelExtrema(MagickWand * wand,const ChannelType channel,size_t * minima,size_t * maxima)1366 WandExport MagickBooleanType MagickGetImageChannelExtrema(MagickWand *wand,
1367 const ChannelType channel,size_t *minima,size_t *maxima)
1368 {
1369 MagickBooleanType
1370 status;
1371
1372 assert(wand != (MagickWand *) NULL);
1373 assert(wand->signature == WandSignature);
1374 if (wand->debug != MagickFalse)
1375 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1376 if (wand->images == (Image *) NULL)
1377 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1378 status=GetImageChannelExtrema(wand->images,channel,minima,maxima,
1379 wand->exception);
1380 return(status);
1381 }
1382
1383 /*
1384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1385 % %
1386 % %
1387 % %
1388 + M a g i c k G e t I m a g e E x t r e m a %
1389 % %
1390 % %
1391 % %
1392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393 %
1394 % MagickGetImageExtrema() gets the extrema for the image.
1395 %
1396 % The format of the MagickGetImageExtrema method is:
1397 %
1398 % MagickBooleanType MagickGetImageExtrema(MagickWand *wand,
1399 % size_t *minima,size_t *maxima)
1400 %
1401 % A description of each parameter follows:
1402 %
1403 % o wand: the magick wand.
1404 %
1405 % o minima: The minimum pixel value for the specified channel(s).
1406 %
1407 % o maxima: The maximum pixel value for the specified channel(s).
1408 %
1409 */
MagickGetImageExtrema(MagickWand * wand,size_t * minima,size_t * maxima)1410 WandExport MagickBooleanType MagickGetImageExtrema(MagickWand *wand,
1411 size_t *minima,size_t *maxima)
1412 {
1413 MagickBooleanType
1414 status;
1415
1416 assert(wand != (MagickWand *) NULL);
1417 assert(wand->signature == WandSignature);
1418 if (wand->debug != MagickFalse)
1419 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1420 if (wand->images == (Image *) NULL)
1421 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1422 status=GetImageExtrema(wand->images,minima,maxima,wand->exception);
1423 return(status);
1424 }
1425
1426 /*
1427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428 % %
1429 % %
1430 % %
1431 % M a g i c k G e t I m a g e M a t t e %
1432 % %
1433 % %
1434 % %
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 %
1437 % MagickGetImageMatte() returns MagickTrue if the image has a matte channel
1438 % otherwise MagickFalse.
1439 %
1440 % The format of the MagickGetImageMatte method is:
1441 %
1442 % size_t MagickGetImageMatte(MagickWand *wand)
1443 %
1444 % A description of each parameter follows:
1445 %
1446 % o wand: the magick wand.
1447 %
1448 */
MagickGetImageMatte(MagickWand * wand)1449 WandExport MagickBooleanType MagickGetImageMatte(MagickWand *wand)
1450 {
1451 assert(wand != (MagickWand *) NULL);
1452 assert(wand->signature == WandSignature);
1453 if (wand->debug != MagickFalse)
1454 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1455 if (wand->images == (Image *) NULL)
1456 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1457 return(wand->images->matte);
1458 }
1459
1460 /*
1461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462 % %
1463 % %
1464 % %
1465 % M a g i c k G e t I m a g e P i x e l s %
1466 % %
1467 % %
1468 % %
1469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470 %
1471 % MagickGetImagePixels() extracts pixel data from an image and returns it to
1472 % you. The method returns MagickTrue on success otherwise MagickFalse if an
1473 % error is encountered. The data is returned as char, short int, int, ssize_t,
1474 % float, or double in the order specified by map.
1475 %
1476 % Suppose you want to extract the first scanline of a 640x480 image as
1477 % character data in red-green-blue order:
1478 %
1479 % MagickGetImagePixels(wand,0,0,640,1,"RGB",CharPixel,pixels);
1480 %
1481 % The format of the MagickGetImagePixels method is:
1482 %
1483 % MagickBooleanType MagickGetImagePixels(MagickWand *wand,
1484 % const ssize_t x,const ssize_t y,const size_t columns,
1485 % const size_t rows,const char *map,const StorageType storage,
1486 % void *pixels)
1487 %
1488 % A description of each parameter follows:
1489 %
1490 % o wand: the magick wand.
1491 %
1492 % o x, y, columns, rows: These values define the perimeter
1493 % of a region of pixels you want to extract.
1494 %
1495 % o map: This string reflects the expected ordering of the pixel array.
1496 % It can be any combination or order of R = red, G = green, B = blue,
1497 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
1498 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
1499 % P = pad.
1500 %
1501 % o storage: Define the data type of the pixels. Float and double types are
1502 % expected to be normalized [0..1] otherwise [0..QuantumRange]. Choose from
1503 % these types: CharPixel, DoublePixel, FloatPixel, IntegerPixel,
1504 % LongPixel, QuantumPixel, or ShortPixel.
1505 %
1506 % o pixels: This array of values contain the pixel components as defined by
1507 % map and type. You must preallocate this array where the expected
1508 % length varies depending on the values of width, height, map, and type.
1509 %
1510 */
MagickGetImagePixels(MagickWand * wand,const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,const char * map,const StorageType storage,void * pixels)1511 WandExport MagickBooleanType MagickGetImagePixels(MagickWand *wand,
1512 const ssize_t x,const ssize_t y,const size_t columns,
1513 const size_t rows,const char *map,const StorageType storage,
1514 void *pixels)
1515 {
1516 return(MagickExportImagePixels(wand,x,y,columns,rows,map,storage,pixels));
1517 }
1518
1519 /*
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521 % %
1522 % %
1523 % %
1524 % M a g i c k G e t I m a g e S i z e %
1525 % %
1526 % %
1527 % %
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1529 %
1530 % MagickGetImageSize() returns the image length in bytes.
1531 %
1532 % The format of the MagickGetImageSize method is:
1533 %
1534 % MagickBooleanType MagickGetImageSize(MagickWand *wand,
1535 % MagickSizeType *length)
1536 %
1537 % A description of each parameter follows:
1538 %
1539 % o wand: the magick wand.
1540 %
1541 % o length: the image length in bytes.
1542 %
1543 */
MagickGetImageSize(MagickWand * wand)1544 WandExport MagickSizeType MagickGetImageSize(MagickWand *wand)
1545 {
1546 assert(wand != (MagickWand *) NULL);
1547 assert(wand->signature == WandSignature);
1548 if (wand->debug != MagickFalse)
1549 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1550 if (wand->images == (Image *) NULL)
1551 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1552 return(GetBlobSize(wand->images));
1553 }
1554
1555 /*
1556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1557 % %
1558 % %
1559 % %
1560 % M a g i c k M a p I m a g e %
1561 % %
1562 % %
1563 % %
1564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565 %
1566 % MagickMapImage() replaces the colors of an image with the closest color
1567 % from a reference image.
1568 %
1569 % The format of the MagickMapImage method is:
1570 %
1571 % MagickBooleanType MagickMapImage(MagickWand *wand,
1572 % const MagickWand *map_wand,const MagickBooleanType dither)
1573 %
1574 % A description of each parameter follows:
1575 %
1576 % o wand: the magick wand.
1577 %
1578 % o map: the map wand.
1579 %
1580 % o dither: Set this integer value to something other than zero to dither
1581 % the mapped image.
1582 %
1583 */
MagickMapImage(MagickWand * wand,const MagickWand * map_wand,const MagickBooleanType dither)1584 WandExport MagickBooleanType MagickMapImage(MagickWand *wand,
1585 const MagickWand *map_wand,const MagickBooleanType dither)
1586 {
1587 MagickBooleanType
1588 status;
1589
1590 assert(wand != (MagickWand *) NULL);
1591 assert(wand->signature == WandSignature);
1592 if (wand->debug != MagickFalse)
1593 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1594 if ((wand->images == (Image *) NULL) || (map_wand->images == (Image *) NULL))
1595 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1596 status=MapImage(wand->images,map_wand->images,dither);
1597 if (status == MagickFalse)
1598 InheritException(wand->exception,&wand->images->exception);
1599 return(status);
1600 }
1601
1602 /*
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604 % %
1605 % %
1606 % %
1607 % M a g i c k M a t t e F l o o d f i l l I m a g e %
1608 % %
1609 % %
1610 % %
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 %
1613 % MagickMatteFloodfillImage() changes the transparency value of any pixel that
1614 % matches target and is an immediate neighbor. If the method
1615 % FillToBorderMethod is specified, the transparency value is changed for any
1616 % neighbor pixel that does not match the bordercolor member of image.
1617 %
1618 % The format of the MagickMatteFloodfillImage method is:
1619 %
1620 % MagickBooleanType MagickMatteFloodfillImage(MagickWand *wand,
1621 % const double alpha,const double fuzz,const PixelWand *bordercolor,
1622 % const ssize_t x,const ssize_t y)
1623 %
1624 % A description of each parameter follows:
1625 %
1626 % o wand: the magick wand.
1627 %
1628 % o alpha: the level of transparency: 1.0 is fully opaque and 0.0 is fully
1629 % transparent.
1630 %
1631 % o fuzz: By default target must match a particular pixel color
1632 % exactly. However, in many cases two colors may differ by a small amount.
1633 % The fuzz member of image defines how much tolerance is acceptable to
1634 % consider two colors as the same. For example, set fuzz to 10 and the
1635 % color red at intensities of 100 and 102 respectively are now interpreted
1636 % as the same color for the purposes of the floodfill.
1637 %
1638 % o bordercolor: the border color pixel wand.
1639 %
1640 % o x,y: the starting location of the operation.
1641 %
1642 */
MagickMatteFloodfillImage(MagickWand * wand,const double alpha,const double fuzz,const PixelWand * bordercolor,const ssize_t x,const ssize_t y)1643 WandExport MagickBooleanType MagickMatteFloodfillImage(MagickWand *wand,
1644 const double alpha,const double fuzz,const PixelWand *bordercolor,
1645 const ssize_t x,const ssize_t y)
1646 {
1647 DrawInfo
1648 *draw_info;
1649
1650 MagickBooleanType
1651 status;
1652
1653 PixelPacket
1654 target;
1655
1656 assert(wand != (MagickWand *) NULL);
1657 assert(wand->signature == WandSignature);
1658 if (wand->debug != MagickFalse)
1659 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1660 if (wand->images == (Image *) NULL)
1661 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1662 draw_info=CloneDrawInfo(wand->image_info,(DrawInfo *) NULL);
1663 (void) GetOneVirtualPixel(wand->images,x % wand->images->columns,
1664 y % wand->images->rows,&target,wand->exception);
1665 if (bordercolor != (PixelWand *) NULL)
1666 PixelGetQuantumColor(bordercolor,&target);
1667 wand->images->fuzz=fuzz;
1668 status=MatteFloodfillImage(wand->images,target,ClampToQuantum(
1669 (MagickRealType) QuantumRange-QuantumRange*alpha),x,y,bordercolor !=
1670 (PixelWand *) NULL ? FillToBorderMethod : FloodfillMethod);
1671 if (status == MagickFalse)
1672 InheritException(wand->exception,&wand->images->exception);
1673 draw_info=DestroyDrawInfo(draw_info);
1674 return(status);
1675 }
1676
1677 /*
1678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679 % %
1680 % %
1681 % %
1682 % M a g i c k M e d i a n F i l t e r I m a g e %
1683 % %
1684 % %
1685 % %
1686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1687 %
1688 % MagickMedianFilterImage() applies a digital filter that improves the quality
1689 % of a noisy image. Each pixel is replaced by the median in a set of
1690 % neighboring pixels as defined by radius.
1691 %
1692 % The format of the MagickMedianFilterImage method is:
1693 %
1694 % MagickBooleanType MagickMedianFilterImage(MagickWand *wand,
1695 % const double radius)
1696 %
1697 % A description of each parameter follows:
1698 %
1699 % o wand: the magick wand.
1700 %
1701 % o radius: the radius of the pixel neighborhood.
1702 %
1703 */
MagickMedianFilterImage(MagickWand * wand,const double radius)1704 WandExport MagickBooleanType MagickMedianFilterImage(MagickWand *wand,
1705 const double radius)
1706 {
1707 Image
1708 *median_image;
1709
1710 assert(wand != (MagickWand *) NULL);
1711 assert(wand->signature == WandSignature);
1712 if (wand->debug != MagickFalse)
1713 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1714 if (wand->images == (Image *) NULL)
1715 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1716 median_image=MedianFilterImage(wand->images,radius,wand->exception);
1717 if (median_image == (Image *) NULL)
1718 return(MagickFalse);
1719 ReplaceImageInList(&wand->images,median_image);
1720 return(MagickTrue);
1721 }
1722
1723 /*
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % %
1726 % %
1727 % %
1728 % M a g i c k M i n i m u m I m a g e s %
1729 % %
1730 % %
1731 % %
1732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733 %
1734 % MagickMinimumImages() returns the minimum intensity of an image sequence.
1735 %
1736 % The format of the MagickMinimumImages method is:
1737 %
1738 % MagickWand *MagickMinimumImages(MagickWand *wand)
1739 %
1740 % A description of each parameter follows:
1741 %
1742 % o wand: the magick wand.
1743 %
1744 */
MagickMinimumImages(MagickWand * wand)1745 WandExport MagickWand *MagickMinimumImages(MagickWand *wand)
1746 {
1747 Image
1748 *minimum_image;
1749
1750 assert(wand != (MagickWand *) NULL);
1751 assert(wand->signature == WandSignature);
1752 if (wand->debug != MagickFalse)
1753 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1754 if (wand->images == (Image *) NULL)
1755 return((MagickWand *) NULL);
1756 minimum_image=EvaluateImages(wand->images,MinEvaluateOperator,
1757 wand->exception);
1758 if (minimum_image == (Image *) NULL)
1759 return((MagickWand *) NULL);
1760 return(CloneMagickWandFromImages(wand,minimum_image));
1761 }
1762
1763 /*
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1765 % %
1766 % %
1767 % %
1768 % M a g i c k M o d e I m a g e %
1769 % %
1770 % %
1771 % %
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773 %
1774 % MagickModeImage() makes each pixel the 'predominant color' of the
1775 % neighborhood of the specified radius.
1776 %
1777 % The format of the MagickModeImage method is:
1778 %
1779 % MagickBooleanType MagickModeImage(MagickWand *wand,
1780 % const double radius)
1781 %
1782 % A description of each parameter follows:
1783 %
1784 % o wand: the magick wand.
1785 %
1786 % o radius: the radius of the pixel neighborhood.
1787 %
1788 */
MagickModeImage(MagickWand * wand,const double radius)1789 WandExport MagickBooleanType MagickModeImage(MagickWand *wand,
1790 const double radius)
1791 {
1792 Image
1793 *mode_image;
1794
1795 assert(wand != (MagickWand *) NULL);
1796 assert(wand->signature == WandSignature);
1797 if (wand->debug != MagickFalse)
1798 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1799 if (wand->images == (Image *) NULL)
1800 ThrowWandException(WandError,"ContainsNoImages",wand->name);
1801 mode_image=ModeImage(wand->images,radius,wand->exception);
1802 if (mode_image == (Image *) NULL)
1803 return(MagickFalse);
1804 ReplaceImageInList(&wand->images,mode_image);
1805 return(MagickTrue);
1806 }
1807
1808 /*
1809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1810 % %
1811 % %
1812 % %
1813 % M a g i c k M o s a i c I m a g e s %
1814 % %
1815 % %
1816 % %
1817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1818 %
1819 % MagickMosaicImages() inlays an image sequence to form a single coherent
1820 % picture. It returns a wand with each image in the sequence composited at
1821 % the location defined by the page offset of the image.
1822 %
1823 % The format of the MagickMosaicImages method is:
1824 %
1825 % MagickWand *MagickMosaicImages(MagickWand *wand)
1826 %
1827 % A description of each parameter follows:
1828 %
1829 % o wand: the magick wand.
1830 %
1831 */
MagickMosaicImages(MagickWand * wand)1832 WandExport MagickWand *MagickMosaicImages(MagickWand *wand)
1833 {
1834 Image
1835 *mosaic_image;
1836
1837 assert(wand != (MagickWand *) NULL);
1838 assert(wand->signature == WandSignature);
1839 if (wand->debug != MagickFalse)
1840 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1841 if (wand->images == (Image *) NULL)
1842 return((MagickWand *) NULL);
1843 mosaic_image=MosaicImages(wand->images,wand->exception);
1844 if (mosaic_image == (Image *) NULL)
1845 return((MagickWand *) NULL);
1846 return(CloneMagickWandFromImages(wand,mosaic_image));
1847 }
1848
1849 /*
1850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1851 % %
1852 % %
1853 % %
1854 % M a g i c k O p a q u e I m a g e %
1855 % %
1856 % %
1857 % %
1858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1859 %
1860 % MagickOpaqueImage() changes any pixel that matches color with the color
1861 % defined by fill.
1862 %
1863 % The format of the MagickOpaqueImage method is:
1864 %
1865 % MagickBooleanType MagickOpaqueImage(MagickWand *wand,
1866 % const PixelWand *target,const PixelWand *fill,const double fuzz)
1867 %
1868 % A description of each parameter follows:
1869 %
1870 % o wand: the magick wand.
1871 %
1872 % o channel: the channel(s).
1873 %
1874 % o target: Change this target color to the fill color within the image.
1875 %
1876 % o fill: the fill pixel wand.
1877 %
1878 % o fuzz: By default target must match a particular pixel color
1879 % exactly. However, in many cases two colors may differ by a small amount.
1880 % The fuzz member of image defines how much tolerance is acceptable to
1881 % consider two colors as the same. For example, set fuzz to 10 and the
1882 % color red at intensities of 100 and 102 respectively are now interpreted
1883 % as the same color for the purposes of the floodfill.
1884 %
1885 */
MagickOpaqueImage(MagickWand * wand,const PixelWand * target,const PixelWand * fill,const double fuzz)1886 WandExport MagickBooleanType MagickOpaqueImage(MagickWand *wand,
1887 const PixelWand *target,const PixelWand *fill,const double fuzz)
1888 {
1889 return(MagickPaintOpaqueImage(wand,target,fill,fuzz));
1890 }
1891
1892 /*
1893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894 % %
1895 % %
1896 % %
1897 % M a g i c k P a i n t F l o o d f i l l I m a g e %
1898 % %
1899 % %
1900 % %
1901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902 %
1903 % MagickPaintFloodfillImage() changes the color value of any pixel that matches
1904 % target and is an immediate neighbor. If the method FillToBorderMethod is
1905 % specified, the color value is changed for any neighbor pixel that does not
1906 % match the bordercolor member of image.
1907 %
1908 % The format of the MagickPaintFloodfillImage method is:
1909 %
1910 % MagickBooleanType MagickPaintFloodfillImage(MagickWand *wand,
1911 % const ChannelType channel,const PixelWand *fill,const double fuzz,
1912 % const PixelWand *bordercolor,const ssize_t x,const ssize_t y)
1913 %
1914 % A description of each parameter follows:
1915 %
1916 % o wand: the magick wand.
1917 %
1918 % o channel: the channel(s).
1919 %
1920 % o fill: the floodfill color pixel wand.
1921 %
1922 % o fuzz: By default target must match a particular pixel color
1923 % exactly. However, in many cases two colors may differ by a small amount.
1924 % The fuzz member of image defines how much tolerance is acceptable to
1925 % consider two colors as the same. For example, set fuzz to 10 and the
1926 % color red at intensities of 100 and 102 respectively are now interpreted
1927 % as the same color for the purposes of the floodfill.
1928 %
1929 % o bordercolor: the border color pixel wand.
1930 %
1931 % o x,y: the starting location of the operation.
1932 %
1933 */
MagickPaintFloodfillImage(MagickWand * wand,const ChannelType channel,const PixelWand * fill,const double fuzz,const PixelWand * bordercolor,const ssize_t x,const ssize_t y)1934 WandExport MagickBooleanType MagickPaintFloodfillImage(MagickWand *wand,
1935 const ChannelType channel,const PixelWand *fill,const double fuzz,
1936 const PixelWand *bordercolor,const ssize_t x,const ssize_t y)
1937 {
1938 MagickBooleanType
1939 status;
1940
1941 status=MagickFloodfillPaintImage(wand,channel,fill,fuzz,bordercolor,x,y,
1942 MagickFalse);
1943 return(status);
1944 }
1945
1946 /*
1947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1948 % %
1949 % %
1950 % %
1951 % M a g i c k P a i n t O p a q u e I m a g e %
1952 % %
1953 % %
1954 % %
1955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1956 %
1957 % MagickPaintOpaqueImage() changes any pixel that matches color with the color
1958 % defined by fill.
1959 %
1960 % The format of the MagickPaintOpaqueImage method is:
1961 %
1962 % MagickBooleanType MagickPaintOpaqueImage(MagickWand *wand,
1963 % const PixelWand *target,const PixelWand *fill,const double fuzz)
1964 % MagickBooleanType MagickPaintOpaqueImageChannel(MagickWand *wand,
1965 % const ChannelType channel,const PixelWand *target,
1966 % const PixelWand *fill,const double fuzz)
1967 %
1968 % A description of each parameter follows:
1969 %
1970 % o wand: the magick wand.
1971 %
1972 % o channel: the channel(s).
1973 %
1974 % o target: Change this target color to the fill color within the image.
1975 %
1976 % o fill: the fill pixel wand.
1977 %
1978 % o fuzz: By default target must match a particular pixel color
1979 % exactly. However, in many cases two colors may differ by a small amount.
1980 % The fuzz member of image defines how much tolerance is acceptable to
1981 % consider two colors as the same. For example, set fuzz to 10 and the
1982 % color red at intensities of 100 and 102 respectively are now interpreted
1983 % as the same color for the purposes of the floodfill.
1984 %
1985 */
1986
MagickPaintOpaqueImage(MagickWand * wand,const PixelWand * target,const PixelWand * fill,const double fuzz)1987 WandExport MagickBooleanType MagickPaintOpaqueImage(MagickWand *wand,
1988 const PixelWand *target,const PixelWand *fill,const double fuzz)
1989 {
1990 return(MagickPaintOpaqueImageChannel(wand,DefaultChannels,target,fill,fuzz));
1991 }
1992
MagickPaintOpaqueImageChannel(MagickWand * wand,const ChannelType channel,const PixelWand * target,const PixelWand * fill,const double fuzz)1993 WandExport MagickBooleanType MagickPaintOpaqueImageChannel(MagickWand *wand,
1994 const ChannelType channel,const PixelWand *target,const PixelWand *fill,
1995 const double fuzz)
1996 {
1997 MagickBooleanType
1998 status;
1999
2000 status=MagickOpaquePaintImageChannel(wand,channel,target,fill,fuzz,
2001 MagickFalse);
2002 return(status);
2003 }
2004
2005 /*
2006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007 % %
2008 % %
2009 % %
2010 % M a g i c k P a i n t T r a n s p a r e n t I m a g e %
2011 % %
2012 % %
2013 % %
2014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2015 %
2016 % MagickPaintTransparentImage() changes any pixel that matches color with the
2017 % color defined by fill.
2018 %
2019 % The format of the MagickPaintTransparentImage method is:
2020 %
2021 % MagickBooleanType MagickPaintTransparentImage(MagickWand *wand,
2022 % const PixelWand *target,const double alpha,const double fuzz)
2023 %
2024 % A description of each parameter follows:
2025 %
2026 % o wand: the magick wand.
2027 %
2028 % o target: Change this target color to specified opacity value within
2029 % the image.
2030 %
2031 % o alpha: the level of transparency: 1.0 is fully opaque and 0.0 is fully
2032 % transparent.
2033 %
2034 % o fuzz: By default target must match a particular pixel color
2035 % exactly. However, in many cases two colors may differ by a small amount.
2036 % The fuzz member of image defines how much tolerance is acceptable to
2037 % consider two colors as the same. For example, set fuzz to 10 and the
2038 % color red at intensities of 100 and 102 respectively are now interpreted
2039 % as the same color for the purposes of the floodfill.
2040 %
2041 */
MagickPaintTransparentImage(MagickWand * wand,const PixelWand * target,const double alpha,const double fuzz)2042 WandExport MagickBooleanType MagickPaintTransparentImage(MagickWand *wand,
2043 const PixelWand *target,const double alpha,const double fuzz)
2044 {
2045 return(MagickTransparentPaintImage(wand,target,alpha,fuzz,MagickFalse));
2046 }
2047
2048 /*
2049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050 % %
2051 % %
2052 % %
2053 % M a g i c k R a d i a l B l u r I m a g e %
2054 % %
2055 % %
2056 % %
2057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2058 %
2059 % MagickRadialBlurImage() radial blurs an image.
2060 %
2061 % The format of the MagickRadialBlurImage method is:
2062 %
2063 % MagickBooleanType MagickRadialBlurImage(MagickWand *wand,
2064 % const double angle)
2065 % MagickBooleanType MagickRadialBlurImageChannel(MagickWand *wand,
2066 % const ChannelType channel,const double angle)
2067 %
2068 % A description of each parameter follows:
2069 %
2070 % o wand: the magick wand.
2071 %
2072 % o channel: the image channel(s).
2073 %
2074 % o angle: the angle of the blur in degrees.
2075 %
2076 */
MagickRadialBlurImage(MagickWand * wand,const double angle)2077 WandExport MagickBooleanType MagickRadialBlurImage(MagickWand *wand,
2078 const double angle)
2079 {
2080 return(MagickRotationalBlurImage(wand,angle));
2081 }
2082
MagickRadialBlurImageChannel(MagickWand * wand,const ChannelType channel,const double angle)2083 WandExport MagickBooleanType MagickRadialBlurImageChannel(MagickWand *wand,
2084 const ChannelType channel,const double angle)
2085 {
2086 return(MagickRotationalBlurImageChannel(wand,channel,angle));
2087 }
2088
2089 /*
2090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2091 % %
2092 % %
2093 % %
2094 % M a g i c k R e c o l o r I m a g e %
2095 % %
2096 % %
2097 % %
2098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2099 %
2100 % MagickRecolorImage() apply color transformation to an image. The method
2101 % permits saturation changes, hue rotation, luminance to alpha, and various
2102 % other effects. Although variable-sized transformation matrices can be used,
2103 % typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
2104 % (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
2105 % except offsets are in column 6 rather than 5 (in support of CMYKA images)
2106 % and offsets are normalized (divide Flash offset by 255).
2107 %
2108 % The format of the MagickRecolorImage method is:
2109 %
2110 % MagickBooleanType MagickRecolorImage(MagickWand *wand,
2111 % const size_t order,const double *color_matrix)
2112 %
2113 % A description of each parameter follows:
2114 %
2115 % o wand: the magick wand.
2116 %
2117 % o order: the number of columns and rows in the color matrix.
2118 %
2119 % o color_matrix: An array of doubles representing the color matrix.
2120 %
2121 */
MagickRecolorImage(MagickWand * wand,const size_t order,const double * color_matrix)2122 WandExport MagickBooleanType MagickRecolorImage(MagickWand *wand,
2123 const size_t order,const double *color_matrix)
2124 {
2125 Image
2126 *transform_image;
2127
2128 assert(wand != (MagickWand *) NULL);
2129 assert(wand->signature == WandSignature);
2130 if (wand->debug != MagickFalse)
2131 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2132 if (color_matrix == (const double *) NULL)
2133 return(MagickFalse);
2134 if (wand->images == (Image *) NULL)
2135 ThrowWandException(WandError,"ContainsNoImages",wand->name);
2136 transform_image=RecolorImage(wand->images,order,color_matrix,
2137 wand->exception);
2138 if (transform_image == (Image *) NULL)
2139 return(MagickFalse);
2140 ReplaceImageInList(&wand->images,transform_image);
2141 return(MagickTrue);
2142 }
2143
2144 /*
2145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2146 % %
2147 % %
2148 % %
2149 % M a g i c k R e d u c e N o i s e I m a g e %
2150 % %
2151 % %
2152 % %
2153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2154 %
2155 % MagickReduceNoiseImage() smooths the contours of an image while still
2156 % preserving edge information. The algorithm works by replacing each pixel
2157 % with its neighbor closest in value. A neighbor is defined by radius. Use
2158 % a radius of 0 and ReduceNoise() selects a suitable radius for you.
2159 %
2160 % The format of the MagickReduceNoiseImage method is:
2161 %
2162 % MagickBooleanType MagickReduceNoiseImage(MagickWand *wand,
2163 % const double radius)
2164 %
2165 % A description of each parameter follows:
2166 %
2167 % o wand: the magick wand.
2168 %
2169 % o radius: the radius of the pixel neighborhood.
2170 %
2171 */
MagickReduceNoiseImage(MagickWand * wand,const double radius)2172 WandExport MagickBooleanType MagickReduceNoiseImage(MagickWand *wand,
2173 const double radius)
2174 {
2175 Image
2176 *noise_image;
2177
2178 assert(wand != (MagickWand *) NULL);
2179 assert(wand->signature == WandSignature);
2180 if (wand->debug != MagickFalse)
2181 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2182 if (wand->images == (Image *) NULL)
2183 ThrowWandException(WandError,"ContainsNoImages",wand->name);
2184 noise_image=ReduceNoiseImage(wand->images,radius,wand->exception);
2185 if (noise_image == (Image *) NULL)
2186 return(MagickFalse);
2187 ReplaceImageInList(&wand->images,noise_image);
2188 return(MagickTrue);
2189 }
2190
2191 /*
2192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2193 % %
2194 % %
2195 % %
2196 % M a g i c k M a x i m u m I m a g e s %
2197 % %
2198 % %
2199 % %
2200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2201 %
2202 % MagickMaximumImages() returns the maximum intensity of an image sequence.
2203 %
2204 % The format of the MagickMaximumImages method is:
2205 %
2206 % MagickWand *MagickMaximumImages(MagickWand *wand)
2207 %
2208 % A description of each parameter follows:
2209 %
2210 % o wand: the magick wand.
2211 %
2212 */
MagickMaximumImages(MagickWand * wand)2213 WandExport MagickWand *MagickMaximumImages(MagickWand *wand)
2214 {
2215 Image
2216 *maximum_image;
2217
2218 assert(wand != (MagickWand *) NULL);
2219 assert(wand->signature == WandSignature);
2220 if (wand->debug != MagickFalse)
2221 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2222 if (wand->images == (Image *) NULL)
2223 return((MagickWand *) NULL);
2224 maximum_image=EvaluateImages(wand->images,MaxEvaluateOperator,
2225 wand->exception);
2226 if (maximum_image == (Image *) NULL)
2227 return((MagickWand *) NULL);
2228 return(CloneMagickWandFromImages(wand,maximum_image));
2229 }
2230
2231 /*
2232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233 % %
2234 % %
2235 % %
2236 % M a g i c k S e t I m a g e A t t r i b u t e %
2237 % %
2238 % %
2239 % %
2240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2241 %
2242 % MagickSetImageAttribute() associates a property with an image.
2243 %
2244 % The format of the MagickSetImageAttribute method is:
2245 %
2246 % MagickBooleanType MagickSetImageAttribute(MagickWand *wand,
2247 % const char *property,const char *value)
2248 %
2249 % A description of each parameter follows:
2250 %
2251 % o wand: the magick wand.
2252 %
2253 % o property: the property.
2254 %
2255 % o value: the value.
2256 %
2257 */
MagickSetImageAttribute(MagickWand * wand,const char * property,const char * value)2258 WandExport MagickBooleanType MagickSetImageAttribute(MagickWand *wand,
2259 const char *property,const char *value)
2260 {
2261 return(SetImageProperty(wand->images,property,value));
2262 }
2263
2264 /*
2265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2266 % %
2267 % %
2268 % %
2269 % M a g i c k S e t I m a g e I n d e x %
2270 % %
2271 % %
2272 % %
2273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 %
2275 % MagickSetImageIndex() set the current image to the position of the list
2276 % specified with the index parameter.
2277 %
2278 % The format of the MagickSetImageIndex method is:
2279 %
2280 % MagickBooleanType MagickSetImageIndex(MagickWand *wand,
2281 % const ssize_t index)
2282 %
2283 % A description of each parameter follows:
2284 %
2285 % o wand: the magick wand.
2286 %
2287 % o index: the scene number.
2288 %
2289 */
MagickSetImageIndex(MagickWand * wand,const ssize_t index)2290 WandExport MagickBooleanType MagickSetImageIndex(MagickWand *wand,
2291 const ssize_t index)
2292 {
2293 return(MagickSetIteratorIndex(wand,index));
2294 }
2295
2296 /*
2297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2298 % %
2299 % %
2300 % %
2301 + M a g i c k S e t I m a g e O p t i o n %
2302 % %
2303 % %
2304 % %
2305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2306 %
2307 % MagickSetImageOption() associates one or options with a particular image
2308 % format (.e.g MagickSetImageOption(wand,"jpeg","perserve","yes").
2309 %
2310 % The format of the MagickSetImageOption method is:
2311 %
2312 % MagickBooleanType MagickSetImageOption(MagickWand *wand,
2313 % const char *format,const char *key,const char *value)
2314 %
2315 % A description of each parameter follows:
2316 %
2317 % o wand: the magick wand.
2318 %
2319 % o format: the image format.
2320 %
2321 % o key: The key.
2322 %
2323 % o value: The value.
2324 %
2325 */
MagickSetImageOption(MagickWand * wand,const char * format,const char * key,const char * value)2326 WandExport MagickBooleanType MagickSetImageOption(MagickWand *wand,
2327 const char *format,const char *key,const char *value)
2328 {
2329 char
2330 option[MaxTextExtent];
2331
2332 assert(wand != (MagickWand *) NULL);
2333 assert(wand->signature == WandSignature);
2334 if (wand->debug != MagickFalse)
2335 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2336 (void) FormatLocaleString(option,MaxTextExtent,"%s:%s=%s",format,key,value);
2337 return(DefineImageOption(wand->image_info,option));
2338 }
2339
2340 /*
2341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342 % %
2343 % %
2344 % %
2345 % M a g i c k T r a n s p a r e n t I m a g e %
2346 % %
2347 % %
2348 % %
2349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2350 %
2351 % MagickTransparentImage() changes any pixel that matches color with the
2352 % color defined by fill.
2353 %
2354 % The format of the MagickTransparentImage method is:
2355 %
2356 % MagickBooleanType MagickTransparentImage(MagickWand *wand,
2357 % const PixelWand *target,const double alpha,const double fuzz)
2358 %
2359 % A description of each parameter follows:
2360 %
2361 % o wand: the magick wand.
2362 %
2363 % o target: Change this target color to specified opacity value within
2364 % the image.
2365 %
2366 % o alpha: the level of transparency: 1.0 is fully opaque and 0.0 is fully
2367 % transparent.
2368 %
2369 % o fuzz: By default target must match a particular pixel color
2370 % exactly. However, in many cases two colors may differ by a small amount.
2371 % The fuzz member of image defines how much tolerance is acceptable to
2372 % consider two colors as the same. For example, set fuzz to 10 and the
2373 % color red at intensities of 100 and 102 respectively are now interpreted
2374 % as the same color for the purposes of the floodfill.
2375 %
2376 */
MagickTransparentImage(MagickWand * wand,const PixelWand * target,const double alpha,const double fuzz)2377 WandExport MagickBooleanType MagickTransparentImage(MagickWand *wand,
2378 const PixelWand *target,const double alpha,const double fuzz)
2379 {
2380 return(MagickPaintTransparentImage(wand,target,alpha,fuzz));
2381 }
2382
2383 /*
2384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2385 % %
2386 % %
2387 % %
2388 % M a g i c k R e g i o n O f I n t e r e s t I m a g e %
2389 % %
2390 % %
2391 % %
2392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2393 %
2394 % MagickRegionOfInterestImage() extracts a region of the image and returns it
2395 % as a new wand.
2396 %
2397 % The format of the MagickRegionOfInterestImage method is:
2398 %
2399 % MagickWand *MagickRegionOfInterestImage(MagickWand *wand,
2400 % const size_t width,const size_t height,const ssize_t x,
2401 % const ssize_t y)
2402 %
2403 % A description of each parameter follows:
2404 %
2405 % o wand: the magick wand.
2406 %
2407 % o width: the region width.
2408 %
2409 % o height: the region height.
2410 %
2411 % o x: the region x offset.
2412 %
2413 % o y: the region y offset.
2414 %
2415 */
MagickRegionOfInterestImage(MagickWand * wand,const size_t width,const size_t height,const ssize_t x,const ssize_t y)2416 WandExport MagickWand *MagickRegionOfInterestImage(MagickWand *wand,
2417 const size_t width,const size_t height,const ssize_t x,
2418 const ssize_t y)
2419 {
2420 return(MagickGetImageRegion(wand,width,height,x,y));
2421 }
2422
2423 /*
2424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2425 % %
2426 % %
2427 % %
2428 % M a g i c k S e t I m a g e P i x e l s %
2429 % %
2430 % %
2431 % %
2432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2433 %
2434 % MagickSetImagePixels() accepts pixel datand stores it in the image at the
2435 % location you specify. The method returns MagickFalse on success otherwise
2436 % MagickTrue if an error is encountered. The pixel data can be either char,
2437 % short int, int, ssize_t, float, or double in the order specified by map.
2438 %
2439 % Suppose your want to upload the first scanline of a 640x480 image from
2440 % character data in red-green-blue order:
2441 %
2442 % MagickSetImagePixels(wand,0,0,640,1,"RGB",CharPixel,pixels);
2443 %
2444 % The format of the MagickSetImagePixels method is:
2445 %
2446 % MagickBooleanType MagickSetImagePixels(MagickWand *wand,
2447 % const ssize_t x,const ssize_t y,const size_t columns,
2448 % const size_t rows,const char *map,const StorageType storage,
2449 % const void *pixels)
2450 %
2451 % A description of each parameter follows:
2452 %
2453 % o wand: the magick wand.
2454 %
2455 % o x, y, columns, rows: These values define the perimeter of a region
2456 % of pixels you want to define.
2457 %
2458 % o map: This string reflects the expected ordering of the pixel array.
2459 % It can be any combination or order of R = red, G = green, B = blue,
2460 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2461 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2462 % P = pad.
2463 %
2464 % o storage: Define the data type of the pixels. Float and double types are
2465 % expected to be normalized [0..1] otherwise [0..QuantumRange]. Choose from
2466 % these types: CharPixel, ShortPixel, IntegerPixel, LongPixel, FloatPixel,
2467 % or DoublePixel.
2468 %
2469 % o pixels: This array of values contain the pixel components as defined by
2470 % map and type. You must preallocate this array where the expected
2471 % length varies depending on the values of width, height, map, and type.
2472 %
2473 */
MagickSetImagePixels(MagickWand * wand,const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,const char * map,const StorageType storage,const void * pixels)2474 WandExport MagickBooleanType MagickSetImagePixels(MagickWand *wand,
2475 const ssize_t x,const ssize_t y,const size_t columns,
2476 const size_t rows,const char *map,const StorageType storage,
2477 const void *pixels)
2478 {
2479 return(MagickImportImagePixels(wand,x,y,columns,rows,map,storage,pixels));
2480 }
2481
2482 /*
2483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2484 % %
2485 % %
2486 % %
2487 % M a g i c k W r i t e I m a g e B l o b %
2488 % %
2489 % %
2490 % %
2491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2492 %
2493 % MagickWriteImageBlob() implements direct to memory image formats. It
2494 % returns the image as a blob and its length. Use MagickSetFormat() to
2495 % set the format of the returned blob (GIF, JPEG, PNG, etc.).
2496 %
2497 % Use MagickRelinquishMemory() to free the blob when you are done with it.
2498 %
2499 % The format of the MagickWriteImageBlob method is:
2500 %
2501 % unsigned char *MagickWriteImageBlob(MagickWand *wand,size_t *length)
2502 %
2503 % A description of each parameter follows:
2504 %
2505 % o wand: the magick wand.
2506 %
2507 % o length: the length of the blob.
2508 %
2509 */
MagickWriteImageBlob(MagickWand * wand,size_t * length)2510 WandExport unsigned char *MagickWriteImageBlob(MagickWand *wand,size_t *length)
2511 {
2512 return(MagickGetImageBlob(wand,length));
2513 }
2514
2515 /*
2516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2517 % %
2518 % %
2519 % %
2520 % N e w P i x e l V i e w %
2521 % %
2522 % %
2523 % %
2524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2525 %
2526 % NewPixelView() returns a pixel view required for all other methods in the
2527 % Pixel View API.
2528 %
2529 % The format of the NewPixelView method is:
2530 %
2531 % PixelView *NewPixelView(MagickWand *wand)
2532 %
2533 % A description of each parameter follows:
2534 %
2535 % o wand: the wand.
2536 %
2537 */
2538
AcquirePixelsThreadSet(const size_t number_wands,const size_t number_threads)2539 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands,
2540 const size_t number_threads)
2541 {
2542 PixelWand
2543 ***pixel_wands;
2544
2545 ssize_t
2546 i;
2547
2548 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
2549 sizeof(*pixel_wands));
2550 if (pixel_wands == (PixelWand ***) NULL)
2551 return((PixelWand ***) NULL);
2552 (void) memset(pixel_wands,0,number_threads*sizeof(*pixel_wands));
2553 for (i=0; i < (ssize_t) number_threads; i++)
2554 {
2555 pixel_wands[i]=NewPixelWands(number_wands);
2556 if (pixel_wands[i] == (PixelWand **) NULL)
2557 return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
2558 }
2559 return(pixel_wands);
2560 }
2561
NewPixelView(MagickWand * wand)2562 WandExport PixelView *NewPixelView(MagickWand *wand)
2563 {
2564 PixelView
2565 *pixel_view;
2566
2567 assert(wand != (MagickWand *) NULL);
2568 assert(wand->signature == MagickCoreSignature);
2569 pixel_view=(PixelView *) AcquireMagickMemory(sizeof(*pixel_view));
2570 if (pixel_view == (PixelView *) NULL)
2571 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
2572 GetExceptionMessage(errno));
2573 (void) memset(pixel_view,0,sizeof(*pixel_view));
2574 pixel_view->id=AcquireWandId();
2575 (void) FormatLocaleString(pixel_view->name,MaxTextExtent,"%s-%.20g",
2576 PixelViewId,(double) pixel_view->id);
2577 pixel_view->exception=AcquireExceptionInfo();
2578 pixel_view->wand=wand;
2579 pixel_view->view=AcquireVirtualCacheView(pixel_view->wand->images,
2580 pixel_view->exception);
2581 pixel_view->region.width=wand->images->columns;
2582 pixel_view->region.height=wand->images->rows;
2583 pixel_view->number_threads=GetOpenMPMaximumThreads();
2584 pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
2585 pixel_view->number_threads);
2586 if (pixel_view->pixel_wands == (PixelWand ***) NULL)
2587 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
2588 GetExceptionMessage(errno));
2589 pixel_view->debug=IsEventLogging();
2590 pixel_view->signature=WandSignature;
2591 return(pixel_view);
2592 }
2593
2594 /*
2595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2596 % %
2597 % %
2598 % %
2599 % N e w P i x e l V i e w R e g i o n %
2600 % %
2601 % %
2602 % %
2603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2604 %
2605 % NewPixelViewRegion() returns a pixel view required for all other methods
2606 % in the Pixel View API.
2607 %
2608 % The format of the NewPixelViewRegion method is:
2609 %
2610 % PixelView *NewPixelViewRegion(MagickWand *wand,const ssize_t x,
2611 % const ssize_t y,const size_t width,const size_t height)
2612 %
2613 % A description of each parameter follows:
2614 %
2615 % o wand: the magick wand.
2616 %
2617 % o x,y,columns,rows: These values define the perimeter of a region of
2618 % pixel_wands view.
2619 %
2620 */
NewPixelViewRegion(MagickWand * wand,const ssize_t x,const ssize_t y,const size_t width,const size_t height)2621 WandExport PixelView *NewPixelViewRegion(MagickWand *wand,const ssize_t x,
2622 const ssize_t y,const size_t width,const size_t height)
2623 {
2624 PixelView
2625 *pixel_view;
2626
2627 assert(wand != (MagickWand *) NULL);
2628 assert(wand->signature == MagickCoreSignature);
2629 pixel_view=(PixelView *) AcquireMagickMemory(sizeof(*pixel_view));
2630 if (pixel_view == (PixelView *) NULL)
2631 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
2632 GetExceptionMessage(errno));
2633 (void) memset(pixel_view,0,sizeof(*pixel_view));
2634 pixel_view->id=AcquireWandId();
2635 (void) FormatLocaleString(pixel_view->name,MaxTextExtent,"%s-%.20g",
2636 PixelViewId,(double) pixel_view->id);
2637 pixel_view->exception=AcquireExceptionInfo();
2638 pixel_view->view=AcquireVirtualCacheView(pixel_view->wand->images,
2639 pixel_view->exception);
2640 pixel_view->wand=wand;
2641 pixel_view->region.width=width;
2642 pixel_view->region.height=height;
2643 pixel_view->region.x=x;
2644 pixel_view->region.y=y;
2645 pixel_view->number_threads=GetOpenMPMaximumThreads();
2646 pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
2647 pixel_view->number_threads);
2648 if (pixel_view->pixel_wands == (PixelWand ***) NULL)
2649 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
2650 GetExceptionMessage(errno));
2651 pixel_view->debug=IsEventLogging();
2652 pixel_view->signature=WandSignature;
2653 return(pixel_view);
2654 }
2655
2656 /*
2657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2658 % %
2659 % %
2660 % %
2661 % P i x e l G e t N e x t R o w %
2662 % %
2663 % %
2664 % %
2665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2666 %
2667 % PixelGetNextRow() returns the next row as an array of pixel wands from the
2668 % pixel iterator.
2669 %
2670 % The format of the PixelGetNextRow method is:
2671 %
2672 % PixelWand **PixelGetNextRow(PixelIterator *iterator,
2673 % size_t *number_wands)
2674 %
2675 % A description of each parameter follows:
2676 %
2677 % o iterator: the pixel iterator.
2678 %
2679 % o number_wands: the number of pixel wands.
2680 %
2681 */
PixelGetNextRow(PixelIterator * iterator)2682 WandExport PixelWand **PixelGetNextRow(PixelIterator *iterator)
2683 {
2684 size_t
2685 number_wands;
2686
2687 return(PixelGetNextIteratorRow(iterator,&number_wands));
2688 }
2689
2690 /*
2691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2692 % %
2693 % %
2694 % %
2695 % P i x e l I t e r a t o r G e t E x c e p t i o n %
2696 % %
2697 % %
2698 % %
2699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2700 %
2701 % PixelIteratorGetException() returns the severity, reason, and description of
2702 % any error that occurs when using other methods in this API.
2703 %
2704 % The format of the PixelIteratorGetException method is:
2705 %
2706 % char *PixelIteratorGetException(const Pixeliterator *iterator,
2707 % ExceptionType *severity)
2708 %
2709 % A description of each parameter follows:
2710 %
2711 % o iterator: the pixel iterator.
2712 %
2713 % o severity: the severity of the error is returned here.
2714 %
2715 */
PixelIteratorGetException(const PixelIterator * iterator,ExceptionType * severity)2716 WandExport char *PixelIteratorGetException(const PixelIterator *iterator,
2717 ExceptionType *severity)
2718 {
2719 return(PixelGetIteratorException(iterator,severity));
2720 }
2721
2722 /*
2723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2724 % %
2725 % %
2726 % %
2727 % S e t P i x e l V i e w I t e r a t o r %
2728 % %
2729 % %
2730 % %
2731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2732 %
2733 % SetPixelViewIterator() iterates over the pixel view in parallel and calls
2734 % your set method for each scanline of the view. The pixel region is
2735 % confined to the image canvas-- that is no negative offsets or widths or
2736 % heights that exceed the image dimension. The pixels are initiallly
2737 % undefined and any settings you make in the callback method are automagically
2738 % synced back to your image.
2739 %
2740 % Use this pragma:
2741 %
2742 % #pragma omp critical
2743 %
2744 % to define a section of code in your callback set method that must be
2745 % executed by a single thread at a time.
2746 %
2747 % The format of the SetPixelViewIterator method is:
2748 %
2749 % MagickBooleanType SetPixelViewIterator(PixelView *destination,
2750 % SetPixelViewMethod set,void *context)
2751 %
2752 % A description of each parameter follows:
2753 %
2754 % o destination: the pixel view.
2755 %
2756 % o set: the set callback method.
2757 %
2758 % o context: the user defined context.
2759 %
2760 */
SetPixelViewIterator(PixelView * destination,SetPixelViewMethod set,void * context)2761 WandExport MagickBooleanType SetPixelViewIterator(PixelView *destination,
2762 SetPixelViewMethod set,void *context)
2763 {
2764 #define SetPixelViewTag "PixelView/Set"
2765
2766 ExceptionInfo
2767 *exception;
2768
2769 Image
2770 *destination_image;
2771
2772 MagickBooleanType
2773 status;
2774
2775 MagickOffsetType
2776 progress;
2777
2778 ssize_t
2779 y;
2780
2781 assert(destination != (PixelView *) NULL);
2782 assert(destination->signature == WandSignature);
2783 if (set == (SetPixelViewMethod) NULL)
2784 return(MagickFalse);
2785 destination_image=destination->wand->images;
2786 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
2787 return(MagickFalse);
2788 status=MagickTrue;
2789 progress=0;
2790 exception=destination->exception;
2791 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2792 #pragma omp parallel for schedule(static) shared(progress,status)
2793 #endif
2794 for (y=destination->region.y; y < (ssize_t) destination->region.height; y++)
2795 {
2796 const int
2797 id = GetOpenMPThreadId();
2798
2799 MagickBooleanType
2800 sync;
2801
2802 IndexPacket
2803 *magick_restrict indexes;
2804
2805 ssize_t
2806 x;
2807
2808 PixelPacket
2809 *magick_restrict pixels;
2810
2811 if (status == MagickFalse)
2812 continue;
2813 pixels=GetCacheViewAuthenticPixels(destination->view,destination->region.x,
2814 y,destination->region.width,1,exception);
2815 if (pixels == (PixelPacket *) NULL)
2816 {
2817 InheritException(destination->exception,GetCacheViewException(
2818 destination->view));
2819 status=MagickFalse;
2820 continue;
2821 }
2822 indexes=GetCacheViewAuthenticIndexQueue(destination->view);
2823 if (set(destination,context) == MagickFalse)
2824 status=MagickFalse;
2825 for (x=0; x < (ssize_t) destination->region.width; x++)
2826 PixelGetQuantumColor(destination->pixel_wands[id][x],pixels+x);
2827 if (destination_image->colorspace == CMYKColorspace)
2828 for (x=0; x < (ssize_t) destination->region.width; x++)
2829 SetPixelIndex(indexes+x,PixelGetBlackQuantum(
2830 destination->pixel_wands[id][x]));
2831 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
2832 if (sync == MagickFalse)
2833 {
2834 InheritException(destination->exception,GetCacheViewException(
2835 destination->view));
2836 status=MagickFalse;
2837 }
2838 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
2839 {
2840 MagickBooleanType
2841 proceed;
2842
2843 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2844 #pragma omp atomic
2845 #endif
2846 progress++;
2847 proceed=SetImageProgress(destination_image,SetPixelViewTag,progress,
2848 destination->region.height);
2849 if (proceed == MagickFalse)
2850 status=MagickFalse;
2851 }
2852 }
2853 return(status);
2854 }
2855
2856 /*
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858 % %
2859 % %
2860 % %
2861 % T r a n s f e r P i x e l V i e w I t e r a t o r %
2862 % %
2863 % %
2864 % %
2865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2866 %
2867 % TransferPixelViewIterator() iterates over two pixel views in parallel and
2868 % calls your transfer method for each scanline of the view. The source pixel
2869 % region is not confined to the image canvas-- that is you can include
2870 % negative offsets or widths or heights that exceed the image dimension.
2871 % However, the destination pixel view is confined to the image canvas-- that
2872 % is no negative offsets or widths or heights that exceed the image dimension
2873 % are permitted.
2874 %
2875 % Use this pragma:
2876 %
2877 % #pragma omp critical
2878 %
2879 % to define a section of code in your callback transfer method that must be
2880 % executed by a single thread at a time.
2881 %
2882 % The format of the TransferPixelViewIterator method is:
2883 %
2884 % MagickBooleanType TransferPixelViewIterator(PixelView *source,
2885 % PixelView *destination,TransferPixelViewMethod transfer,void *context)
2886 %
2887 % A description of each parameter follows:
2888 %
2889 % o source: the source pixel view.
2890 %
2891 % o destination: the destination pixel view.
2892 %
2893 % o transfer: the transfer callback method.
2894 %
2895 % o context: the user defined context.
2896 %
2897 */
TransferPixelViewIterator(PixelView * source,PixelView * destination,TransferPixelViewMethod transfer,void * context)2898 WandExport MagickBooleanType TransferPixelViewIterator(PixelView *source,
2899 PixelView *destination,TransferPixelViewMethod transfer,void *context)
2900 {
2901 #define TransferPixelViewTag "PixelView/Transfer"
2902
2903 ExceptionInfo
2904 *exception;
2905
2906 Image
2907 *destination_image,
2908 *source_image;
2909
2910 MagickBooleanType
2911 status;
2912
2913 MagickOffsetType
2914 progress;
2915
2916 ssize_t
2917 y;
2918
2919 assert(source != (PixelView *) NULL);
2920 assert(source->signature == WandSignature);
2921 if (transfer == (TransferPixelViewMethod) NULL)
2922 return(MagickFalse);
2923 source_image=source->wand->images;
2924 destination_image=destination->wand->images;
2925 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
2926 return(MagickFalse);
2927 status=MagickTrue;
2928 progress=0;
2929 exception=destination->exception;
2930 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2931 #pragma omp parallel for schedule(static) shared(progress,status)
2932 #endif
2933 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
2934 {
2935 const int
2936 id = GetOpenMPThreadId();
2937
2938 MagickBooleanType
2939 sync;
2940
2941 const IndexPacket
2942 *magick_restrict indexes;
2943
2944 const PixelPacket
2945 *magick_restrict pixels;
2946
2947 IndexPacket
2948 *magick_restrict destination_indexes;
2949
2950 ssize_t
2951 x;
2952
2953 PixelPacket
2954 *magick_restrict destination_pixels;
2955
2956 if (status == MagickFalse)
2957 continue;
2958 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
2959 source->region.width,1,source->exception);
2960 if (pixels == (const PixelPacket *) NULL)
2961 {
2962 status=MagickFalse;
2963 continue;
2964 }
2965 indexes=GetCacheViewVirtualIndexQueue(source->view);
2966 for (x=0; x < (ssize_t) source->region.width; x++)
2967 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
2968 if (source_image->colorspace == CMYKColorspace)
2969 for (x=0; x < (ssize_t) source->region.width; x++)
2970 PixelSetBlackQuantum(source->pixel_wands[id][x],
2971 GetPixelIndex(indexes+x));
2972 if (source_image->storage_class == PseudoClass)
2973 for (x=0; x < (ssize_t) source->region.width; x++)
2974 PixelSetIndex(source->pixel_wands[id][x],
2975 GetPixelIndex(indexes+x));
2976 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
2977 destination->region.x,y,destination->region.width,1,exception);
2978 if (destination_pixels == (PixelPacket *) NULL)
2979 {
2980 status=MagickFalse;
2981 continue;
2982 }
2983 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
2984 for (x=0; x < (ssize_t) destination->region.width; x++)
2985 PixelSetQuantumColor(destination->pixel_wands[id][x],pixels+x);
2986 if (destination_image->colorspace == CMYKColorspace)
2987 for (x=0; x < (ssize_t) destination->region.width; x++)
2988 PixelSetBlackQuantum(destination->pixel_wands[id][x],
2989 GetPixelIndex(indexes+x));
2990 if (destination_image->storage_class == PseudoClass)
2991 for (x=0; x < (ssize_t) destination->region.width; x++)
2992 PixelSetIndex(destination->pixel_wands[id][x],
2993 GetPixelIndex(indexes+x));
2994 if (transfer(source,destination,context) == MagickFalse)
2995 status=MagickFalse;
2996 for (x=0; x < (ssize_t) destination->region.width; x++)
2997 PixelGetQuantumColor(destination->pixel_wands[id][x],
2998 destination_pixels+x);
2999 if (destination_image->colorspace == CMYKColorspace)
3000 for (x=0; x < (ssize_t) destination->region.width; x++)
3001 SetPixelIndex(destination_indexes+x,PixelGetBlackQuantum(
3002 destination->pixel_wands[id][x]));
3003 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
3004 if (sync == MagickFalse)
3005 {
3006 InheritException(destination->exception,GetCacheViewException(
3007 source->view));
3008 status=MagickFalse;
3009 }
3010 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
3011 {
3012 MagickBooleanType
3013 proceed;
3014
3015 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3016 #pragma omp atomic
3017 #endif
3018 progress++;
3019 proceed=SetImageProgress(source_image,TransferPixelViewTag,progress,
3020 source->region.height);
3021 if (proceed == MagickFalse)
3022 status=MagickFalse;
3023 }
3024 }
3025 return(status);
3026 }
3027
3028 /*
3029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030 % %
3031 % %
3032 % %
3033 % U p d a t e P i x e l V i e w I t e r a t o r %
3034 % %
3035 % %
3036 % %
3037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3038 %
3039 % UpdatePixelViewIterator() iterates over the pixel view in parallel and calls
3040 % your update method for each scanline of the view. The pixel region is
3041 % confined to the image canvas-- that is no negative offsets or widths or
3042 % heights that exceed the image dimension are permitted. Updates to pixels
3043 % in your callback are automagically synced back to the image.
3044 %
3045 % Use this pragma:
3046 %
3047 % #pragma omp critical
3048 %
3049 % to define a section of code in your callback update method that must be
3050 % executed by a single thread at a time.
3051 %
3052 % The format of the UpdatePixelViewIterator method is:
3053 %
3054 % MagickBooleanType UpdatePixelViewIterator(PixelView *source,
3055 % UpdatePixelViewMethod update,void *context)
3056 %
3057 % A description of each parameter follows:
3058 %
3059 % o source: the source pixel view.
3060 %
3061 % o update: the update callback method.
3062 %
3063 % o context: the user defined context.
3064 %
3065 */
UpdatePixelViewIterator(PixelView * source,UpdatePixelViewMethod update,void * context)3066 WandExport MagickBooleanType UpdatePixelViewIterator(PixelView *source,
3067 UpdatePixelViewMethod update,void *context)
3068 {
3069 #define UpdatePixelViewTag "PixelView/Update"
3070
3071 ExceptionInfo
3072 *exception;
3073
3074 Image
3075 *source_image;
3076
3077 MagickBooleanType
3078 status;
3079
3080 MagickOffsetType
3081 progress;
3082
3083 ssize_t
3084 y;
3085
3086 assert(source != (PixelView *) NULL);
3087 assert(source->signature == WandSignature);
3088 if (update == (UpdatePixelViewMethod) NULL)
3089 return(MagickFalse);
3090 source_image=source->wand->images;
3091 if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
3092 return(MagickFalse);
3093 status=MagickTrue;
3094 progress=0;
3095 exception=source->exception;
3096 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3097 #pragma omp parallel for schedule(static) shared(progress,status)
3098 #endif
3099 for (y=source->region.y; y < (ssize_t) source->region.height; y++)
3100 {
3101 const int
3102 id = GetOpenMPThreadId();
3103
3104 IndexPacket
3105 *magick_restrict indexes;
3106
3107 ssize_t
3108 x;
3109
3110 PixelPacket
3111 *magick_restrict pixels;
3112
3113 if (status == MagickFalse)
3114 continue;
3115 pixels=GetCacheViewAuthenticPixels(source->view,source->region.x,y,
3116 source->region.width,1,exception);
3117 if (pixels == (PixelPacket *) NULL)
3118 {
3119 InheritException(source->exception,GetCacheViewException(
3120 source->view));
3121 status=MagickFalse;
3122 continue;
3123 }
3124 indexes=GetCacheViewAuthenticIndexQueue(source->view);
3125 for (x=0; x < (ssize_t) source->region.width; x++)
3126 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
3127 if (source_image->colorspace == CMYKColorspace)
3128 for (x=0; x < (ssize_t) source->region.width; x++)
3129 PixelSetBlackQuantum(source->pixel_wands[id][x],
3130 GetPixelIndex(indexes+x));
3131 if (update(source,context) == MagickFalse)
3132 status=MagickFalse;
3133 for (x=0; x < (ssize_t) source->region.width; x++)
3134 PixelGetQuantumColor(source->pixel_wands[id][x],pixels+x);
3135 if (source_image->colorspace == CMYKColorspace)
3136 for (x=0; x < (ssize_t) source->region.width; x++)
3137 SetPixelIndex(indexes+x,PixelGetBlackQuantum(
3138 source->pixel_wands[id][x]));
3139 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
3140 {
3141 InheritException(source->exception,GetCacheViewException(source->view));
3142 status=MagickFalse;
3143 }
3144 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
3145 {
3146 MagickBooleanType
3147 proceed;
3148
3149 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3150 #pragma omp atomic
3151 #endif
3152 progress++;
3153 proceed=SetImageProgress(source_image,UpdatePixelViewTag,progress,
3154 source->region.height);
3155 if (proceed == MagickFalse)
3156 status=MagickFalse;
3157 }
3158 }
3159 return(status);
3160 }
3161 #endif
3162