blob: de049e7907c47f95afac797c825cda307f8bbfc8 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP IIIII X X EEEEE L %
7% P P I X X E L %
8% PPPP I X EEE L %
9% P I X X E L %
10% P IIIII X X EEEEE LLLLL %
11% %
12% V V IIIII EEEEE W W %
13% V V I E W W %
14% V V I EEE W W W %
15% V V I E WW WW %
16% V IIIII EEEEE W W %
17% %
18% %
19% MagickWand Pixel View Methods %
20% %
21% Software Design %
22% John Cristy %
23% March 2003 %
24% %
25% %
cristy16af1cb2009-12-11 21:38:29 +000026% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000027% dedicated to making software imaging solutions freely available. %
28% %
29% You may not use this file except in compliance with the License. You may %
30% obtain a copy of the License at %
31% %
32% http://www.imagemagick.org/script/license.php %
33% %
34% Unless required by applicable law or agreed to in writing, software %
35% distributed under the License is distributed on an "AS IS" BASIS, %
36% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
37% See the License for the specific language governing permissions and %
38% limitations under the License. %
39% %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42%
43%
44*/
45
46/*
47 Include declarations.
48*/
49#include "wand/studio.h"
50#include "wand/MagickWand.h"
51#include "wand/magick-wand-private.h"
52#include "wand/wand.h"
53#include "magick/monitor-private.h"
54#include "magick/thread-private.h"
55/*
56 Define declarations.
57*/
58#define PixelViewId "PixelView"
59
60/*
61 Typedef declarations.
62*/
63struct _PixelView
64{
65 unsigned long
66 id;
67
68 char
69 name[MaxTextExtent];
70
71 ExceptionInfo
72 *exception;
73
74 MagickWand
75 *wand;
76
77 CacheView
78 *view;
79
80 RectangleInfo
81 region;
82
83 unsigned long
84 number_threads;
85
86 PixelWand
87 ***pixel_wands;
88
89 MagickBooleanType
90 debug;
91
92 unsigned long
93 signature;
94};
95
96/*
97%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98% %
99% %
100% %
101% C l o n e P i x e l V i e w %
102% %
103% %
104% %
105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106%
107% ClonePixelView() makes a copy of the specified pixel view.
108%
109% The format of the ClonePixelView method is:
110%
111% PixelView *ClonePixelView(const PixelView *pixel_view)
112%
113% A description of each parameter follows:
114%
115% o pixel_view: the pixel view.
116%
117*/
118WandExport PixelView *ClonePixelView(const PixelView *pixel_view)
119{
120 PixelView
121 *clone_view;
122
123 register long
124 i;
125
126 assert(pixel_view != (PixelView *) NULL);
127 assert(pixel_view->signature == WandSignature);
128 if (pixel_view->debug != MagickFalse)
129 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
cristy90823212009-12-12 20:48:33 +0000130 clone_view=(PixelView *) AcquireAlignedMemory(1,sizeof(*clone_view));
cristy3ed852e2009-09-05 21:47:34 +0000131 if (clone_view == (PixelView *) NULL)
132 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
133 pixel_view->name);
134 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
135 clone_view->id=AcquireWandId();
136 (void) FormatMagickString(clone_view->name,MaxTextExtent,"%s-%lu",PixelViewId,
137 clone_view->id);
138 clone_view->exception=AcquireExceptionInfo();
139 InheritException(clone_view->exception,pixel_view->exception);
140 clone_view->view=CloneCacheView(pixel_view->view);
141 clone_view->region=pixel_view->region;
142 clone_view->number_threads=pixel_view->number_threads;
143 for (i=0; i < (long) pixel_view->number_threads; i++)
144 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
145 pixel_view->pixel_wands[i],pixel_view->region.width);
146 clone_view->debug=pixel_view->debug;
147 if (clone_view->debug != MagickFalse)
148 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
149 clone_view->signature=WandSignature;
150 return(clone_view);
151}
152
153/*
154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155% %
156% %
157% %
158% D e s t r o y P i x e l V i e w %
159% %
160% %
161% %
162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163%
164% DestroyPixelView() deallocates memory associated with a pixel view.
165%
166% The format of the DestroyPixelView method is:
167%
168% PixelView *DestroyPixelView(PixelView *pixel_view,
169% const unsigned long number_wands,const unsigned long number_threads)
170%
171% A description of each parameter follows:
172%
173% o pixel_view: the pixel view.
174%
175% o number_wand: the number of pixel wands.
176%
177% o number_threads: number of threads.
178%
179*/
180
181static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
182 const unsigned long number_wands,const unsigned long number_threads)
183{
184 register long
185 i;
186
187 assert(pixel_wands != (PixelWand ***) NULL);
188 for (i=0; i < (long) number_threads; i++)
189 if (pixel_wands[i] != (PixelWand **) NULL)
190 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
191 pixel_wands=(PixelWand ***) RelinquishAlignedMemory(pixel_wands);
192 return(pixel_wands);
193}
194
195WandExport PixelView *DestroyPixelView(PixelView *pixel_view)
196{
197 assert(pixel_view != (PixelView *) NULL);
198 assert(pixel_view->signature == WandSignature);
199 pixel_view->pixel_wands=DestroyPixelsThreadSet(pixel_view->pixel_wands,
200 pixel_view->region.width,pixel_view->number_threads);
201 pixel_view->view=DestroyCacheView(pixel_view->view);
202 pixel_view->exception=DestroyExceptionInfo(pixel_view->exception);
203 pixel_view->signature=(~WandSignature);
204 RelinquishWandId(pixel_view->id);
205 pixel_view=(PixelView *) RelinquishMagickMemory(pixel_view);
206 return(pixel_view);
207}
208
209/*
210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211% %
212% %
213% %
214% 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 %
215% %
216% %
217% %
218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219%
220% DuplexTransferPixelViewIterator() iterates over three pixel views in
221% parallel and calls your transfer method for each scanline of the view. The
222% source and duplex pixel region is not confined to the image canvas-- that is
223% you can include negative offsets or widths or heights that exceed the image
224% dimension. However, the destination pixel view is confined to the image
225% canvas-- that is no negative offsets or widths or heights that exceed the
226% image dimension are permitted.
227%
228% Use this pragma:
229%
230% #pragma omp critical
231%
232% to define a section of code in your callback transfer method that must be
233% executed by a single thread at a time.
234%
235% The format of the DuplexTransferPixelViewIterator method is:
236%
237% MagickBooleanType DuplexTransferPixelViewIterator(PixelView *source,
238% PixelView *duplex,PixelView *destination,
239% DuplexTransferPixelViewMethod transfer,void *context)
240%
241% A description of each parameter follows:
242%
243% o source: the source pixel view.
244%
245% o duplex: the duplex pixel view.
246%
247% o destination: the destination pixel view.
248%
249% o transfer: the transfer callback method.
250%
251% o context: the user defined context.
252%
253*/
254WandExport MagickBooleanType DuplexTransferPixelViewIterator(
255 PixelView *source,PixelView *duplex,PixelView *destination,
256 DuplexTransferPixelViewMethod transfer,void *context)
257{
258#define DuplexTransferPixelViewTag "PixelView/DuplexTransfer"
259
260 ExceptionInfo
261 *exception;
262
263 Image
264 *destination_image,
265 *duplex_image,
266 *source_image;
267
268 long
269 progress,
270 y;
271
272 MagickBooleanType
273 status;
274
275 assert(source != (PixelView *) NULL);
276 assert(source->signature == WandSignature);
277 if (transfer == (DuplexTransferPixelViewMethod) NULL)
278 return(MagickFalse);
279 source_image=source->wand->images;
280 duplex_image=duplex->wand->images;
281 destination_image=destination->wand->images;
282 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
283 return(MagickFalse);
284 status=MagickTrue;
285 progress=0;
286 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +0000287#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristycde47d32009-11-04 03:05:18 +0000288 #pragma omp parallel for schedule(static,1) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000289#endif
290 for (y=source->region.y; y < (long) source->region.height; y++)
291 {
292 MagickBooleanType
293 sync;
294
295 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000296 *restrict duplex_indexes,
297 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000298
299 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000300 *restrict duplex_pixels,
301 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +0000302
303 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000304 *restrict destination_indexes;
cristy3ed852e2009-09-05 21:47:34 +0000305
306 register long
307 id,
308 x;
309
310 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000311 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +0000312
313 if (status == MagickFalse)
314 continue;
315 id=GetOpenMPThreadId();
316 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
317 source->region.width,1,source->exception);
318 if (pixels == (const PixelPacket *) NULL)
319 {
320 status=MagickFalse;
321 continue;
322 }
323 indexes=GetCacheViewVirtualIndexQueue(source->view);
324 for (x=0; x < (long) source->region.width; x++)
325 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
326 if (source_image->colorspace == CMYKColorspace)
327 for (x=0; x < (long) source->region.width; x++)
328 PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
329 if (source_image->storage_class == PseudoClass)
330 for (x=0; x < (long) source->region.width; x++)
331 PixelSetIndex(source->pixel_wands[id][x],indexes[x]);
332 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->region.x,y,
333 duplex->region.width,1,duplex->exception);
334 if (duplex_pixels == (const PixelPacket *) NULL)
335 {
336 status=MagickFalse;
337 continue;
338 }
339 duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
340 for (x=0; x < (long) duplex->region.width; x++)
341 PixelSetQuantumColor(duplex->pixel_wands[id][x],duplex_pixels+x);
342 if (duplex_image->colorspace == CMYKColorspace)
343 for (x=0; x < (long) duplex->region.width; x++)
344 PixelSetBlackQuantum(duplex->pixel_wands[id][x],duplex_indexes[x]);
345 if (duplex_image->storage_class == PseudoClass)
346 for (x=0; x < (long) duplex->region.width; x++)
347 PixelSetIndex(duplex->pixel_wands[id][x],duplex_indexes[x]);
348 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
349 destination->region.x,y,destination->region.width,1,exception);
350 if (destination_pixels == (PixelPacket *) NULL)
351 {
352 status=MagickFalse;
353 continue;
354 }
355 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
356 for (x=0; x < (long) destination->region.width; x++)
357 PixelSetQuantumColor(destination->pixel_wands[id][x],
358 destination_pixels+x);
359 if (destination_image->colorspace == CMYKColorspace)
360 for (x=0; x < (long) destination->region.width; x++)
361 PixelSetBlackQuantum(destination->pixel_wands[id][x],
362 destination_indexes[x]);
363 if (destination_image->storage_class == PseudoClass)
364 for (x=0; x < (long) destination->region.width; x++)
365 PixelSetIndex(destination->pixel_wands[id][x],destination_indexes[x]);
366 if (transfer(source,duplex,destination,context) == MagickFalse)
367 status=MagickFalse;
368 for (x=0; x < (long) destination->region.width; x++)
369 PixelGetQuantumColor(destination->pixel_wands[id][x],
370 destination_pixels+x);
371 if (destination_image->colorspace == CMYKColorspace)
372 for (x=0; x < (long) destination->region.width; x++)
373 destination_indexes[x]=PixelGetBlackQuantum(
374 destination->pixel_wands[id][x]);
375 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
376 if (sync == MagickFalse)
377 {
378 InheritException(destination->exception,GetCacheViewException(
379 source->view));
380 status=MagickFalse;
381 }
382 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
383 {
384 MagickBooleanType
385 proceed;
386
cristyb5d5f722009-11-04 03:03:49 +0000387#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000388 #pragma omp critical (MagickWand_DuplexTransferPixelViewIterator)
389#endif
390 proceed=SetImageProgress(source_image,DuplexTransferPixelViewTag,
391 progress++,source->region.height);
392 if (proceed == MagickFalse)
393 status=MagickFalse;
394 }
395 }
396 return(status);
397}
398
399/*
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401% %
402% %
403% %
404% G e t P i x e l V i e w E x c e p t i o n %
405% %
406% %
407% %
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%
410% GetPixelViewException() returns the severity, reason, and description of any
411% error that occurs when utilizing a pixel view.
412%
413% The format of the GetPixelViewException method is:
414%
415% char *GetPixelViewException(const PixelWand *pixel_view,
416% ExceptionType *severity)
417%
418% A description of each parameter follows:
419%
420% o pixel_view: the pixel pixel_view.
421%
422% o severity: the severity of the error is returned here.
423%
424*/
425WandExport char *GetPixelViewException(const PixelView *pixel_view,
426 ExceptionType *severity)
427{
428 char
429 *description;
430
431 assert(pixel_view != (const PixelView *) NULL);
432 assert(pixel_view->signature == WandSignature);
433 if (pixel_view->debug != MagickFalse)
434 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
435 assert(severity != (ExceptionType *) NULL);
436 *severity=pixel_view->exception->severity;
437 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
438 sizeof(*description));
439 if (description == (char *) NULL)
440 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
441 pixel_view->name);
442 *description='\0';
443 if (pixel_view->exception->reason != (char *) NULL)
444 (void) CopyMagickString(description,GetLocaleExceptionMessage(
445 pixel_view->exception->severity,pixel_view->exception->reason),
446 MaxTextExtent);
447 if (pixel_view->exception->description != (char *) NULL)
448 {
449 (void) ConcatenateMagickString(description," (",MaxTextExtent);
450 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
451 pixel_view->exception->severity,pixel_view->exception->description),
452 MaxTextExtent);
453 (void) ConcatenateMagickString(description,")",MaxTextExtent);
454 }
455 return(description);
456}
457
458/*
459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460% %
461% %
462% %
463% G e t P i x e l V i e w H e i g h t %
464% %
465% %
466% %
467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468%
469% GetPixelViewHeight() returns the pixel view height.
470%
471% The format of the GetPixelViewHeight method is:
472%
473% unsigned long GetPixelViewHeight(const PixelView *pixel_view)
474%
475% A description of each parameter follows:
476%
477% o pixel_view: the pixel view.
478%
479*/
480WandExport unsigned long GetPixelViewHeight(const PixelView *pixel_view)
481{
482 assert(pixel_view != (PixelView *) NULL);
483 assert(pixel_view->signature == WandSignature);
484 return(pixel_view->region.height);
485}
486
487/*
488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
489% %
490% %
491% %
492% G e t P i x e l V i e w I t e r a t o r %
493% %
494% %
495% %
496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497%
498% GetPixelViewIterator() iterates over the pixel view in parallel and calls
499% your get method for each scanline of the view. The pixel region is
500% not confined to the image canvas-- that is you can include negative offsets
501% or widths or heights that exceed the image dimension. Any updates to
502% the pixels in your callback are ignored.
503%
504% Use this pragma:
505%
506% #pragma omp critical
507%
508% to define a section of code in your callback get method that must be
509% executed by a single thread at a time.
510%
511% The format of the GetPixelViewIterator method is:
512%
513% MagickBooleanType GetPixelViewIterator(PixelView *source,
514% GetPixelViewMethod get,void *context)
515%
516% A description of each parameter follows:
517%
518% o source: the source pixel view.
519%
520% o get: the get callback method.
521%
522% o context: the user defined context.
523%
524*/
525WandExport MagickBooleanType GetPixelViewIterator(PixelView *source,
526 GetPixelViewMethod get,void *context)
527{
528#define GetPixelViewTag "PixelView/Get"
529
530 Image
531 *source_image;
532
533 long
534 progress,
535 y;
536
537 MagickBooleanType
538 status;
539
540 assert(source != (PixelView *) NULL);
541 assert(source->signature == WandSignature);
542 if (get == (GetPixelViewMethod) NULL)
543 return(MagickFalse);
544 source_image=source->wand->images;
545 status=MagickTrue;
546 progress=0;
cristyb5d5f722009-11-04 03:03:49 +0000547#if defined(MAGICKCORE_OPENMP_SUPPORT)
548 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000549#endif
550 for (y=source->region.y; y < (long) source->region.height; y++)
551 {
552 register const IndexPacket
553 *indexes;
554
555 register const PixelPacket
556 *pixels;
557
558 register long
559 id,
560 x;
561
562 if (status == MagickFalse)
563 continue;
564 id=GetOpenMPThreadId();
565 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
566 source->region.width,1,source->exception);
567 if (pixels == (const PixelPacket *) NULL)
568 {
569 status=MagickFalse;
570 continue;
571 }
572 indexes=GetCacheViewVirtualIndexQueue(source->view);
573 for (x=0; x < (long) source->region.width; x++)
574 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
575 if (source_image->colorspace == CMYKColorspace)
576 for (x=0; x < (long) source->region.width; x++)
577 PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
578 if (source_image->storage_class == PseudoClass)
579 for (x=0; x < (long) source->region.width; x++)
580 PixelSetIndex(source->pixel_wands[id][x],indexes[x]);
581 if (get(source,context) == MagickFalse)
582 status=MagickFalse;
583 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
584 {
585 MagickBooleanType
586 proceed;
587
cristyb5d5f722009-11-04 03:03:49 +0000588#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000589 #pragma omp critical (MagickWand_GetPixelViewIterator)
590#endif
591 proceed=SetImageProgress(source_image,GetPixelViewTag,progress++,
592 source->region.height);
593 if (proceed == MagickFalse)
594 status=MagickFalse;
595 }
596 }
597 return(status);
598}
599
600/*
601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602% %
603% %
604% %
605% G e t P i x e l V i e w P i x e l s %
606% %
607% %
608% %
609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610%
611% GetPixelViewPixels() returns the pixel view pixel_wands.
612%
613% The format of the GetPixelViewPixels method is:
614%
615% PixelWand *GetPixelViewPixels(const PixelView *pixel_view)
616%
617% A description of each parameter follows:
618%
619% o pixel_view: the pixel view.
620%
621*/
622WandExport PixelWand **GetPixelViewPixels(const PixelView *pixel_view)
623{
624 long
625 id;
626
627 assert(pixel_view != (PixelView *) NULL);
628 assert(pixel_view->signature == WandSignature);
629 id=GetOpenMPThreadId();
630 return(pixel_view->pixel_wands[id]);
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635% %
636% %
637% %
638% G e t P i x e l V i e w W a n d %
639% %
640% %
641% %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
644% GetPixelViewWand() returns the magick wand associated with the pixel view.
645%
646% The format of the GetPixelViewWand method is:
647%
648% MagickWand *GetPixelViewWand(const PixelView *pixel_view)
649%
650% A description of each parameter follows:
651%
652% o pixel_view: the pixel view.
653%
654*/
655WandExport MagickWand *GetPixelViewWand(const PixelView *pixel_view)
656{
657 assert(pixel_view != (PixelView *) NULL);
658 assert(pixel_view->signature == WandSignature);
659 return(pixel_view->wand);
660}
661
662/*
663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664% %
665% %
666% %
667% G e t P i x e l V i e w W i d t h %
668% %
669% %
670% %
671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
672%
673% GetPixelViewWidth() returns the pixel view width.
674%
675% The format of the GetPixelViewWidth method is:
676%
677% unsigned long GetPixelViewWidth(const PixelView *pixel_view)
678%
679% A description of each parameter follows:
680%
681% o pixel_view: the pixel view.
682%
683*/
684WandExport unsigned long GetPixelViewWidth(const PixelView *pixel_view)
685{
686 assert(pixel_view != (PixelView *) NULL);
687 assert(pixel_view->signature == WandSignature);
688 return(pixel_view->region.width);
689}
690
691/*
692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693% %
694% %
695% %
696% G e t P i x e l V i e w X %
697% %
698% %
699% %
700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701%
702% GetPixelViewX() returns the pixel view x offset.
703%
704% The format of the GetPixelViewX method is:
705%
706% long GetPixelViewX(const PixelView *pixel_view)
707%
708% A description of each parameter follows:
709%
710% o pixel_view: the pixel view.
711%
712*/
713WandExport long GetPixelViewX(const PixelView *pixel_view)
714{
715 assert(pixel_view != (PixelView *) NULL);
716 assert(pixel_view->signature == WandSignature);
717 return(pixel_view->region.x);
718}
719
720/*
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722% %
723% %
724% %
725% G e t P i x e l V i e w Y %
726% %
727% %
728% %
729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730%
731% GetPixelViewY() returns the pixel view y offset.
732%
733% The format of the GetPixelViewY method is:
734%
735% long GetPixelViewY(const PixelView *pixel_view)
736%
737% A description of each parameter follows:
738%
739% o pixel_view: the pixel view.
740%
741*/
742WandExport long GetPixelViewY(const PixelView *pixel_view)
743{
744 assert(pixel_view != (PixelView *) NULL);
745 assert(pixel_view->signature == WandSignature);
746 return(pixel_view->region.y);
747}
748
749/*
750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
751% %
752% %
753% %
754% I s P i x e l V i e w %
755% %
756% %
757% %
758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759%
760% IsPixelView() returns MagickTrue if the the parameter is verified as a pixel
761% view container.
762%
763% The format of the IsPixelView method is:
764%
765% MagickBooleanType IsPixelView(const PixelView *pixel_view)
766%
767% A description of each parameter follows:
768%
769% o pixel_view: the pixel view.
770%
771*/
772WandExport MagickBooleanType IsPixelView(const PixelView *pixel_view)
773{
774 size_t
775 length;
776
777 if (pixel_view == (const PixelView *) NULL)
778 return(MagickFalse);
779 if (pixel_view->signature != WandSignature)
780 return(MagickFalse);
781 length=strlen(PixelViewId);
782 if (LocaleNCompare(pixel_view->name,PixelViewId,length) != 0)
783 return(MagickFalse);
784 return(MagickTrue);
785}
786
787/*
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789% %
790% %
791% %
792% N e w P i x e l V i e w %
793% %
794% %
795% %
796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797%
798% NewPixelView() returns a pixel view required for all other methods in the
799% Pixel View API.
800%
801% The format of the NewPixelView method is:
802%
803% PixelView *NewPixelView(MagickWand *wand)
804%
805% A description of each parameter follows:
806%
807% o wand: the wand.
808%
809*/
810
811static PixelWand ***AcquirePixelsThreadSet(const unsigned long number_wands,
812 const unsigned long number_threads)
813{
814 PixelWand
815 ***pixel_wands;
816
817 register long
818 i;
819
820 pixel_wands=(PixelWand ***) AcquireAlignedMemory(number_threads,
821 sizeof(*pixel_wands));
822 if (pixel_wands == (PixelWand ***) NULL)
823 return((PixelWand ***) NULL);
824 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
825 for (i=0; i < (long) number_threads; i++)
826 {
827 pixel_wands[i]=NewPixelWands(number_wands);
828 if (pixel_wands[i] == (PixelWand **) NULL)
829 return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
830 }
831 return(pixel_wands);
832}
833
834WandExport PixelView *NewPixelView(MagickWand *wand)
835{
836 PixelView
837 *pixel_view;
838
839 assert(wand != (MagickWand *) NULL);
840 assert(wand->signature == MagickSignature);
cristy90823212009-12-12 20:48:33 +0000841 pixel_view=(PixelView *) AcquireAlignedMemory(1,sizeof(*pixel_view));
cristy3ed852e2009-09-05 21:47:34 +0000842 if (pixel_view == (PixelView *) NULL)
843 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
844 GetExceptionMessage(errno));
845 (void) ResetMagickMemory(pixel_view,0,sizeof(*pixel_view));
846 pixel_view->id=AcquireWandId();
847 (void) FormatMagickString(pixel_view->name,MaxTextExtent,"%s-%lu",
848 PixelViewId,pixel_view->id);
849 pixel_view->exception=AcquireExceptionInfo();
850 pixel_view->wand=wand;
851 pixel_view->view=AcquireCacheView(pixel_view->wand->images);
852 pixel_view->region.width=wand->images->columns;
853 pixel_view->region.height=wand->images->rows;
854 pixel_view->number_threads=GetOpenMPMaximumThreads();
855 pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
856 pixel_view->number_threads);
857 if (pixel_view->pixel_wands == (PixelWand ***) NULL)
858 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
859 GetExceptionMessage(errno));
860 pixel_view->debug=IsEventLogging();
861 pixel_view->signature=WandSignature;
862 return(pixel_view);
863}
864
865/*
866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867% %
868% %
869% %
870% N e w P i x e l V i e w R e g i o n %
871% %
872% %
873% %
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%
876% NewPixelViewRegion() returns a pixel view required for all other methods
877% in the Pixel View API.
878%
879% The format of the NewPixelViewRegion method is:
880%
881% PixelView *NewPixelViewRegion(MagickWand *wand,const long x,
882% const long y,const unsigned long width,const unsigned long height)
883%
884% A description of each parameter follows:
885%
886% o wand: the magick wand.
887%
888% o x,y,columns,rows: These values define the perimeter of a region of
889% pixel_wands view.
890%
891*/
892WandExport PixelView *NewPixelViewRegion(MagickWand *wand,const long x,
893 const long y,const unsigned long width,const unsigned long height)
894{
895 PixelView
896 *pixel_view;
897
898 assert(wand != (MagickWand *) NULL);
899 assert(wand->signature == MagickSignature);
cristy90823212009-12-12 20:48:33 +0000900 pixel_view=(PixelView *) AcquireAlignedMemory(1,sizeof(*pixel_view));
cristy3ed852e2009-09-05 21:47:34 +0000901 if (pixel_view == (PixelView *) NULL)
902 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
903 GetExceptionMessage(errno));
904 (void) ResetMagickMemory(pixel_view,0,sizeof(*pixel_view));
905 pixel_view->id=AcquireWandId();
906 (void) FormatMagickString(pixel_view->name,MaxTextExtent,"%s-%lu",
907 PixelViewId,pixel_view->id);
908 pixel_view->exception=AcquireExceptionInfo();
909 pixel_view->view=AcquireCacheView(pixel_view->wand->images);
910 pixel_view->wand=wand;
911 pixel_view->region.width=width;
912 pixel_view->region.height=height;
913 pixel_view->region.x=x;
914 pixel_view->region.y=y;
915 pixel_view->number_threads=GetOpenMPMaximumThreads();
916 pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
917 pixel_view->number_threads);
918 if (pixel_view->pixel_wands == (PixelWand ***) NULL)
919 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
920 GetExceptionMessage(errno));
921 pixel_view->debug=IsEventLogging();
922 pixel_view->signature=WandSignature;
923 return(pixel_view);
924}
925
926/*
927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928% %
929% %
930% %
931% S e t P i x e l V i e w I t e r a t o r %
932% %
933% %
934% %
935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936%
937% SetPixelViewIterator() iterates over the pixel view in parallel and calls
938% your set method for each scanline of the view. The pixel region is
939% confined to the image canvas-- that is no negative offsets or widths or
940% heights that exceed the image dimension. The pixels are initiallly
941% undefined and any settings you make in the callback method are automagically
942% synced back to your image.
943%
944% Use this pragma:
945%
946% #pragma omp critical
947%
948% to define a section of code in your callback set method that must be
949% executed by a single thread at a time.
950%
951% The format of the SetPixelViewIterator method is:
952%
953% MagickBooleanType SetPixelViewIterator(PixelView *destination,
954% SetPixelViewMethod set,void *context)
955%
956% A description of each parameter follows:
957%
958% o destination: the pixel view.
959%
960% o set: the set callback method.
961%
962% o context: the user defined context.
963%
964*/
965WandExport MagickBooleanType SetPixelViewIterator(PixelView *destination,
966 SetPixelViewMethod set,void *context)
967{
968#define SetPixelViewTag "PixelView/Set"
969
970 ExceptionInfo
971 *exception;
972
973 Image
974 *destination_image;
975
976 long
977 progress,
978 y;
979
980 MagickBooleanType
981 status;
982
983 assert(destination != (PixelView *) NULL);
984 assert(destination->signature == WandSignature);
985 if (set == (SetPixelViewMethod) NULL)
986 return(MagickFalse);
987 destination_image=destination->wand->images;
988 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
989 return(MagickFalse);
990 status=MagickTrue;
991 progress=0;
992 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +0000993#if defined(MAGICKCORE_OPENMP_SUPPORT)
994 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +0000995#endif
996 for (y=destination->region.y; y < (long) destination->region.height; y++)
997 {
998 MagickBooleanType
999 sync;
1000
1001 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001002 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001003
1004 register long
1005 id,
1006 x;
1007
1008 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001009 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001010
1011 if (status == MagickFalse)
1012 continue;
1013 id=GetOpenMPThreadId();
1014 pixels=GetCacheViewAuthenticPixels(destination->view,destination->region.x,
1015 y,destination->region.width,1,exception);
1016 if (pixels == (PixelPacket *) NULL)
1017 {
1018 InheritException(destination->exception,GetCacheViewException(
1019 destination->view));
1020 status=MagickFalse;
1021 continue;
1022 }
1023 indexes=GetCacheViewAuthenticIndexQueue(destination->view);
1024 if (set(destination,context) == MagickFalse)
1025 status=MagickFalse;
1026 for (x=0; x < (long) destination->region.width; x++)
1027 PixelGetQuantumColor(destination->pixel_wands[id][x],pixels+x);
1028 if (destination_image->colorspace == CMYKColorspace)
1029 for (x=0; x < (long) destination->region.width; x++)
1030 indexes[x]=PixelGetBlackQuantum(destination->pixel_wands[id][x]);
1031 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1032 if (sync == MagickFalse)
1033 {
1034 InheritException(destination->exception,GetCacheViewException(
1035 destination->view));
1036 status=MagickFalse;
1037 }
1038 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
1039 {
1040 MagickBooleanType
1041 proceed;
1042
cristyb5d5f722009-11-04 03:03:49 +00001043#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001044 #pragma omp critical (MagickWand_SetPixelViewIterator)
1045#endif
1046 proceed=SetImageProgress(destination_image,SetPixelViewTag,progress++,
1047 destination->region.height);
1048 if (proceed == MagickFalse)
1049 status=MagickFalse;
1050 }
1051 }
1052 return(status);
1053}
1054
1055/*
1056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1057% %
1058% %
1059% %
1060% 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 %
1061% %
1062% %
1063% %
1064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065%
1066% TransferPixelViewIterator() iterates over two pixel views in parallel and
1067% calls your transfer method for each scanline of the view. The source pixel
1068% region is not confined to the image canvas-- that is you can include
1069% negative offsets or widths or heights that exceed the image dimension.
1070% However, the destination pixel view is confined to the image canvas-- that
1071% is no negative offsets or widths or heights that exceed the image dimension
1072% are permitted.
1073%
1074% Use this pragma:
1075%
1076% #pragma omp critical
1077%
1078% to define a section of code in your callback transfer method that must be
1079% executed by a single thread at a time.
1080%
1081% The format of the TransferPixelViewIterator method is:
1082%
1083% MagickBooleanType TransferPixelViewIterator(PixelView *source,
1084% PixelView *destination,TransferPixelViewMethod transfer,void *context)
1085%
1086% A description of each parameter follows:
1087%
1088% o source: the source pixel view.
1089%
1090% o destination: the destination pixel view.
1091%
1092% o transfer: the transfer callback method.
1093%
1094% o context: the user defined context.
1095%
1096*/
1097WandExport MagickBooleanType TransferPixelViewIterator(PixelView *source,
1098 PixelView *destination,TransferPixelViewMethod transfer,void *context)
1099{
1100#define TransferPixelViewTag "PixelView/Transfer"
1101
1102 ExceptionInfo
1103 *exception;
1104
1105 Image
1106 *destination_image,
1107 *source_image;
1108
1109 long
1110 progress,
1111 y;
1112
1113 MagickBooleanType
1114 status;
1115
1116 assert(source != (PixelView *) NULL);
1117 assert(source->signature == WandSignature);
1118 if (transfer == (TransferPixelViewMethod) NULL)
1119 return(MagickFalse);
1120 source_image=source->wand->images;
1121 destination_image=destination->wand->images;
1122 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
1123 return(MagickFalse);
1124 status=MagickTrue;
1125 progress=0;
1126 exception=destination->exception;
cristyb5d5f722009-11-04 03:03:49 +00001127#if defined(MAGICKCORE_OPENMP_SUPPORT)
1128 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001129#endif
1130 for (y=source->region.y; y < (long) source->region.height; y++)
1131 {
1132 MagickBooleanType
1133 sync;
1134
1135 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001136 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001137
1138 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001139 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001140
1141 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001142 *restrict destination_indexes;
cristy3ed852e2009-09-05 21:47:34 +00001143
1144 register long
1145 id,
1146 x;
1147
1148 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001149 *restrict destination_pixels;
cristy3ed852e2009-09-05 21:47:34 +00001150
1151 if (status == MagickFalse)
1152 continue;
1153 id=GetOpenMPThreadId();
1154 pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
1155 source->region.width,1,source->exception);
1156 if (pixels == (const PixelPacket *) NULL)
1157 {
1158 status=MagickFalse;
1159 continue;
1160 }
1161 indexes=GetCacheViewVirtualIndexQueue(source->view);
1162 for (x=0; x < (long) source->region.width; x++)
1163 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
1164 if (source_image->colorspace == CMYKColorspace)
1165 for (x=0; x < (long) source->region.width; x++)
1166 PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
1167 if (source_image->storage_class == PseudoClass)
1168 for (x=0; x < (long) source->region.width; x++)
1169 PixelSetIndex(source->pixel_wands[id][x],indexes[x]);
1170 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1171 destination->region.x,y,destination->region.width,1,exception);
1172 if (destination_pixels == (PixelPacket *) NULL)
1173 {
1174 status=MagickFalse;
1175 continue;
1176 }
1177 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
1178 for (x=0; x < (long) destination->region.width; x++)
1179 PixelSetQuantumColor(destination->pixel_wands[id][x],pixels+x);
1180 if (destination_image->colorspace == CMYKColorspace)
1181 for (x=0; x < (long) destination->region.width; x++)
1182 PixelSetBlackQuantum(destination->pixel_wands[id][x],indexes[x]);
1183 if (destination_image->storage_class == PseudoClass)
1184 for (x=0; x < (long) destination->region.width; x++)
1185 PixelSetIndex(destination->pixel_wands[id][x],indexes[x]);
1186 if (transfer(source,destination,context) == MagickFalse)
1187 status=MagickFalse;
1188 for (x=0; x < (long) destination->region.width; x++)
1189 PixelGetQuantumColor(destination->pixel_wands[id][x],
1190 destination_pixels+x);
1191 if (destination_image->colorspace == CMYKColorspace)
1192 for (x=0; x < (long) destination->region.width; x++)
1193 destination_indexes[x]=PixelGetBlackQuantum(
1194 destination->pixel_wands[id][x]);
1195 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1196 if (sync == MagickFalse)
1197 {
1198 InheritException(destination->exception,GetCacheViewException(
1199 source->view));
1200 status=MagickFalse;
1201 }
1202 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1203 {
1204 MagickBooleanType
1205 proceed;
1206
cristyb5d5f722009-11-04 03:03:49 +00001207#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001208 #pragma omp critical (MagickWand_TransferPixelViewIterator)
1209#endif
1210 proceed=SetImageProgress(source_image,TransferPixelViewTag,progress++,
1211 source->region.height);
1212 if (proceed == MagickFalse)
1213 status=MagickFalse;
1214 }
1215 }
1216 return(status);
1217}
1218
1219/*
1220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1221% %
1222% %
1223% %
1224% U p d a t e P i x e l V i e w I t e r a t o r %
1225% %
1226% %
1227% %
1228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1229%
1230% UpdatePixelViewIterator() iterates over the pixel view in parallel and calls
1231% your update method for each scanline of the view. The pixel region is
1232% confined to the image canvas-- that is no negative offsets or widths or
1233% heights that exceed the image dimension are permitted. Updates to pixels
1234% in your callback are automagically synced back to the image.
1235%
1236% Use this pragma:
1237%
1238% #pragma omp critical
1239%
1240% to define a section of code in your callback update method that must be
1241% executed by a single thread at a time.
1242%
1243% The format of the UpdatePixelViewIterator method is:
1244%
1245% MagickBooleanType UpdatePixelViewIterator(PixelView *source,
1246% UpdatePixelViewMethod update,void *context)
1247%
1248% A description of each parameter follows:
1249%
1250% o source: the source pixel view.
1251%
1252% o update: the update callback method.
1253%
1254% o context: the user defined context.
1255%
1256*/
1257WandExport MagickBooleanType UpdatePixelViewIterator(PixelView *source,
1258 UpdatePixelViewMethod update,void *context)
1259{
1260#define UpdatePixelViewTag "PixelView/Update"
1261
1262 ExceptionInfo
1263 *exception;
1264
1265 Image
1266 *source_image;
1267
1268 long
1269 progress,
1270 y;
1271
1272 MagickBooleanType
1273 status;
1274
1275 assert(source != (PixelView *) NULL);
1276 assert(source->signature == WandSignature);
1277 if (update == (UpdatePixelViewMethod) NULL)
1278 return(MagickFalse);
1279 source_image=source->wand->images;
1280 if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
1281 return(MagickFalse);
1282 status=MagickTrue;
1283 progress=0;
1284 exception=source->exception;
cristyb5d5f722009-11-04 03:03:49 +00001285#if defined(MAGICKCORE_OPENMP_SUPPORT)
1286 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001287#endif
1288 for (y=source->region.y; y < (long) source->region.height; y++)
1289 {
1290 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001291 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001292
1293 register long
1294 id,
1295 x;
1296
1297 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001298 *restrict pixels;
cristy3ed852e2009-09-05 21:47:34 +00001299
1300 if (status == MagickFalse)
1301 continue;
1302 id=GetOpenMPThreadId();
1303 pixels=GetCacheViewAuthenticPixels(source->view,source->region.x,y,
1304 source->region.width,1,exception);
1305 if (pixels == (PixelPacket *) NULL)
1306 {
1307 InheritException(source->exception,GetCacheViewException(
1308 source->view));
1309 status=MagickFalse;
1310 continue;
1311 }
1312 indexes=GetCacheViewAuthenticIndexQueue(source->view);
1313 for (x=0; x < (long) source->region.width; x++)
1314 PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
1315 if (source_image->colorspace == CMYKColorspace)
1316 for (x=0; x < (long) source->region.width; x++)
1317 PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
1318 if (update(source,context) == MagickFalse)
1319 status=MagickFalse;
1320 for (x=0; x < (long) source->region.width; x++)
1321 PixelGetQuantumColor(source->pixel_wands[id][x],pixels+x);
1322 if (source_image->colorspace == CMYKColorspace)
1323 for (x=0; x < (long) source->region.width; x++)
1324 indexes[x]=PixelGetBlackQuantum(source->pixel_wands[id][x]);
1325 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1326 {
1327 InheritException(source->exception,GetCacheViewException(source->view));
1328 status=MagickFalse;
1329 }
1330 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1331 {
1332 MagickBooleanType
1333 proceed;
1334
cristyb5d5f722009-11-04 03:03:49 +00001335#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001336 #pragma omp critical (MagickWand_UpdatePixelViewIterator)
1337#endif
1338 proceed=SetImageProgress(source_image,UpdatePixelViewTag,progress++,
1339 source->region.height);
1340 if (proceed == MagickFalse)
1341 status=MagickFalse;
1342 }
1343 }
1344 return(status);
1345}