MagickWand  6.7.7
wand-view.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                        W   W   AAA   N   N  DDDD                            %
00006 %                        W   W  A   A  NN  N  D   D                           %
00007 %                        W W W  AAAAA  N N N  D   D                           %
00008 %                        WW WW  A   A  N  NN  D   D                           %
00009 %                        W   W  A   A  N   N  DDDD                            %
00010 %                                                                             %
00011 %                        V   V  IIIII  EEEEE  W   W                           %
00012 %                        V   V    I    E      W   W                           %
00013 %                        V   V    I    EEE    W W W                           %
00014 %                         V V     I    E      WW WW                           %
00015 %                          V    IIIII  EEEEE  W   W                           %
00016 %                                                                             %
00017 %                                                                             %
00018 %                        MagickWand Wand View Methods                         %
00019 %                                                                             %
00020 %                              Software Design                                %
00021 %                                John Cristy                                  %
00022 %                                March 2003                                   %
00023 %                                                                             %
00024 %                                                                             %
00025 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00026 %  dedicated to making software imaging solutions freely available.           %
00027 %                                                                             %
00028 %  You may not use this file except in compliance with the License.  You may  %
00029 %  obtain a copy of the License at                                            %
00030 %                                                                             %
00031 %    http://www.imagemagick.org/script/license.php                            %
00032 %                                                                             %
00033 %  Unless required by applicable law or agreed to in writing, software        %
00034 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00035 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00036 %  See the License for the specific language governing permissions and        %
00037 %  limitations under the License.                                             %
00038 %                                                                             %
00039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00040 %
00041 %
00042 %
00043 */
00044 
00045 /*
00046   Include declarations.
00047 */
00048 #include "MagickWand/studio.h"
00049 #include "MagickWand/MagickWand.h"
00050 #include "MagickWand/magick-wand-private.h"
00051 #include "MagickWand/wand.h"
00052 #include "MagickCore/monitor-private.h"
00053 #include "MagickCore/thread-private.h"
00054 /*
00055  Define declarations.
00056 */
00057 #define WandViewId  "WandView"
00058 
00059 /*
00060   Typedef declarations.
00061 */
00062 struct _WandView
00063 {
00064   size_t
00065     id;
00066 
00067   char
00068     name[MaxTextExtent],
00069     *description;
00070 
00071   RectangleInfo
00072     extent;
00073 
00074   MagickWand
00075     *wand;
00076 
00077   Image
00078     *image;
00079 
00080   CacheView
00081     *view;
00082 
00083   PixelWand
00084     ***pixel_wands;
00085 
00086   ExceptionInfo
00087     *exception;
00088 
00089   MagickBooleanType
00090     debug;
00091 
00092   size_t
00093     signature;
00094 };
00095 
00096 /*
00097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00098 %                                                                             %
00099 %                                                                             %
00100 %                                                                             %
00101 %   C l o n e W a n d V i e w                                                 %
00102 %                                                                             %
00103 %                                                                             %
00104 %                                                                             %
00105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00106 %
00107 %  CloneWandView() makes a copy of the specified wand view.
00108 %
00109 %  The format of the CloneWandView method is:
00110 %
00111 %      WandView *CloneWandView(const WandView *wand_view)
00112 %
00113 %  A description of each parameter follows:
00114 %
00115 %    o wand_view: the wand view.
00116 %
00117 */
00118 WandExport WandView *CloneWandView(const WandView *wand_view)
00119 {
00120   WandView
00121     *clone_view;
00122 
00123   register ssize_t
00124     i;
00125 
00126   assert(wand_view != (WandView *) NULL);
00127   assert(wand_view->signature == WandSignature);
00128   if (wand_view->debug != MagickFalse)
00129     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
00130   clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view));
00131   if (clone_view == (WandView *) NULL)
00132     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00133       wand_view->name);
00134   (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
00135   clone_view->id=AcquireWandId();
00136   (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
00137     WandViewId,(double) clone_view->id);
00138   clone_view->description=ConstantString(wand_view->description);
00139   clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
00140     wand_view->exception);
00141   clone_view->view=CloneCacheView(wand_view->view);
00142   clone_view->extent=wand_view->extent;
00143   clone_view->exception=AcquireExceptionInfo();
00144   InheritException(clone_view->exception,wand_view->exception);
00145   for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
00146     clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
00147       wand_view->pixel_wands[i],wand_view->extent.width);
00148   clone_view->debug=wand_view->debug;
00149   if (clone_view->debug != MagickFalse)
00150     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
00151   clone_view->signature=WandSignature;
00152   return(clone_view);
00153 }
00154 
00155 /*
00156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00157 %                                                                             %
00158 %                                                                             %
00159 %                                                                             %
00160 %   D e s t r o y W a n d V i e w                                             %
00161 %                                                                             %
00162 %                                                                             %
00163 %                                                                             %
00164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00165 %
00166 %  DestroyWandView() deallocates memory associated with a wand view.
00167 %
00168 %  The format of the DestroyWandView method is:
00169 %
00170 %      WandView *DestroyWandView(WandView *wand_view)
00171 %
00172 %  A description of each parameter follows:
00173 %
00174 %    o wand_view: the wand view.
00175 %
00176 */
00177 
00178 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
00179   const size_t number_wands)
00180 {
00181   register ssize_t
00182     i;
00183 
00184   assert(pixel_wands != (PixelWand ***) NULL);
00185   for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
00186     if (pixel_wands[i] != (PixelWand **) NULL)
00187       pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
00188   pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
00189   return(pixel_wands);
00190 }
00191 
00192 WandExport WandView *DestroyWandView(WandView *wand_view)
00193 {
00194   assert(wand_view != (WandView *) NULL);
00195   assert(wand_view->signature == WandSignature);
00196   wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
00197     wand_view->extent.width);
00198   wand_view->image=DestroyImage(wand_view->image);
00199   wand_view->view=DestroyCacheView(wand_view->view);
00200   wand_view->exception=DestroyExceptionInfo(wand_view->exception);
00201   wand_view->signature=(~WandSignature);
00202   RelinquishWandId(wand_view->id);
00203   wand_view=(WandView *) RelinquishMagickMemory(wand_view);
00204   return(wand_view);
00205 }
00206 
00207 /*
00208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00209 %                                                                             %
00210 %                                                                             %
00211 %                                                                             %
00212 %   D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r               %
00213 %                                                                             %
00214 %                                                                             %
00215 %                                                                             %
00216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00217 %
00218 %  DuplexTransferWandViewIterator() iterates over three wand views in
00219 %  parallel and calls your transfer method for each scanline of the view.  The
00220 %  source and duplex pixel extent is not confined to the image canvas-- that is
00221 %  you can include negative offsets or widths or heights that exceed the image
00222 %  dimension.  However, the destination wand view is confined to the image
00223 %  canvas-- that is no negative offsets or widths or heights that exceed the
00224 %  image dimension are permitted.
00225 %
00226 %  The callback signature is:
00227 %
00228 %      MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
00229 %        const WandView *duplex,WandView *destination,const ssize_t y,
00230 %        const int thread_id,void *context)
00231 %
00232 %  Use this pragma if the view is not single threaded:
00233 %
00234 %    #pragma omp critical
00235 %
00236 %  to define a section of code in your callback transfer method that must be
00237 %  executed by a single thread at a time.
00238 %
00239 %  The format of the DuplexTransferWandViewIterator method is:
00240 %
00241 %      MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
00242 %        WandView *duplex,WandView *destination,
00243 %        DuplexTransferWandViewMethod transfer,void *context)
00244 %
00245 %  A description of each parameter follows:
00246 %
00247 %    o source: the source wand view.
00248 %
00249 %    o duplex: the duplex wand view.
00250 %
00251 %    o destination: the destination wand view.
00252 %
00253 %    o transfer: the transfer callback method.
00254 %
00255 %    o context: the user defined context.
00256 %
00257 */
00258 WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
00259   WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
00260   void *context)
00261 {
00262   Image
00263     *destination_image,
00264     *source_image;
00265 
00266   MagickBooleanType
00267     status;
00268 
00269   MagickOffsetType
00270     progress;
00271 
00272   size_t
00273     height,
00274     width;
00275 
00276   ssize_t
00277     y;
00278 
00279   assert(source != (WandView *) NULL);
00280   assert(source->signature == WandSignature);
00281   if (transfer == (DuplexTransferWandViewMethod) NULL)
00282     return(MagickFalse);
00283   source_image=source->wand->images;
00284   destination_image=destination->wand->images;
00285   status=SetImageStorageClass(destination_image,DirectClass,
00286     destination->exception);
00287   if (status == MagickFalse)
00288     return(MagickFalse);
00289   status=MagickTrue;
00290   progress=0;
00291   height=source->extent.height-source->extent.y;
00292   width=source->extent.width-source->extent.x;
00293 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00294   #pragma omp parallel for schedule(static) shared(progress,status) \
00295     dynamic_number_threads(source_image,width,height,1)
00296 #endif
00297   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
00298   {
00299     const int
00300       id = GetOpenMPThreadId();
00301 
00302     MagickBooleanType
00303       sync;
00304 
00305     register const Quantum
00306       *restrict duplex_pixels,
00307       *restrict pixels;
00308 
00309     register ssize_t
00310       x;
00311 
00312     register Quantum
00313       *restrict destination_pixels;
00314 
00315     if (status == MagickFalse)
00316       continue;
00317     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
00318       source->extent.width,1,source->exception);
00319     if (pixels == (const Quantum *) NULL)
00320       {
00321         status=MagickFalse;
00322         continue;
00323       }
00324     for (x=0; x < (ssize_t) source->extent.width; x++)
00325     {
00326       PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
00327       pixels+=GetPixelChannels(source->image);
00328     }
00329     duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
00330       duplex->extent.width,1,duplex->exception);
00331     if (duplex_pixels == (const Quantum *) NULL)
00332       {
00333         status=MagickFalse;
00334         continue;
00335       }
00336     for (x=0; x < (ssize_t) duplex->extent.width; x++)
00337     {
00338       PixelSetQuantumPixel(duplex->image,duplex_pixels,
00339         duplex->pixel_wands[id][x]);
00340       duplex_pixels+=GetPixelChannels(duplex->image);
00341     }
00342     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
00343       destination->extent.x,y,destination->extent.width,1,
00344       destination->exception);
00345     if (destination_pixels == (Quantum *) NULL)
00346       {
00347         status=MagickFalse;
00348         continue;
00349       }
00350     for (x=0; x < (ssize_t) destination->extent.width; x++)
00351     {
00352       PixelSetQuantumPixel(destination->image,destination_pixels,
00353         destination->pixel_wands[id][x]);
00354       destination_pixels+=GetPixelChannels(destination->image);
00355     }
00356     if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
00357       status=MagickFalse;
00358     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
00359       destination->extent.x,y,destination->extent.width,1,
00360       destination->exception);
00361     for (x=0; x < (ssize_t) destination->extent.width; x++)
00362     {
00363       PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
00364         destination_pixels);
00365       destination_pixels+=GetPixelChannels(destination->image);
00366     }
00367     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
00368     if (sync == MagickFalse)
00369       status=MagickFalse;
00370     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
00371       {
00372         MagickBooleanType
00373           proceed;
00374 
00375 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00376         #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
00377 #endif
00378         proceed=SetImageProgress(source_image,source->description,progress++,
00379           source->extent.height);
00380         if (proceed == MagickFalse)
00381           status=MagickFalse;
00382       }
00383   }
00384   return(status);
00385 }
00386 
00387 /*
00388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00389 %                                                                             %
00390 %                                                                             %
00391 %                                                                             %
00392 %   G e t W a n d V i e w E x c e p t i o n                                   %
00393 %                                                                             %
00394 %                                                                             %
00395 %                                                                             %
00396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00397 %
00398 %  GetWandViewException() returns the severity, reason, and description of any
00399 %  error that occurs when utilizing a wand view.
00400 %
00401 %  The format of the GetWandViewException method is:
00402 %
00403 %      char *GetWandViewException(const WandView *wand_view,
00404 %        ExceptionType *severity)
00405 %
00406 %  A description of each parameter follows:
00407 %
00408 %    o wand_view: the pixel wand_view.
00409 %
00410 %    o severity: the severity of the error is returned here.
00411 %
00412 */
00413 WandExport char *GetWandViewException(const WandView *wand_view,
00414   ExceptionType *severity)
00415 {
00416   char
00417     *description;
00418 
00419   assert(wand_view != (const WandView *) NULL);
00420   assert(wand_view->signature == WandSignature);
00421   if (wand_view->debug != MagickFalse)
00422     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
00423   assert(severity != (ExceptionType *) NULL);
00424   *severity=wand_view->exception->severity;
00425   description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
00426     sizeof(*description));
00427   if (description == (char *) NULL)
00428     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00429       wand_view->name);
00430   *description='\0';
00431   if (wand_view->exception->reason != (char *) NULL)
00432     (void) CopyMagickString(description,GetLocaleExceptionMessage(
00433       wand_view->exception->severity,wand_view->exception->reason),
00434         MaxTextExtent);
00435   if (wand_view->exception->description != (char *) NULL)
00436     {
00437       (void) ConcatenateMagickString(description," (",MaxTextExtent);
00438       (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
00439         wand_view->exception->severity,wand_view->exception->description),
00440         MaxTextExtent);
00441       (void) ConcatenateMagickString(description,")",MaxTextExtent);
00442     }
00443   return(description);
00444 }
00445 
00446 /*
00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00448 %                                                                             %
00449 %                                                                             %
00450 %                                                                             %
00451 %   G e t W a n d V i e w E x t e n t                                         %
00452 %                                                                             %
00453 %                                                                             %
00454 %                                                                             %
00455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00456 %
00457 %  GetWandViewExtent() returns the wand view extent.
00458 %
00459 %  The format of the GetWandViewExtent method is:
00460 %
00461 %      RectangleInfo GetWandViewExtent(const WandView *wand_view)
00462 %
00463 %  A description of each parameter follows:
00464 %
00465 %    o wand_view: the wand view.
00466 %
00467 */
00468 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
00469 {
00470   assert(wand_view != (WandView *) NULL);
00471   assert(wand_view->signature == WandSignature);
00472   return(wand_view->extent);
00473 }
00474 
00475 /*
00476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00477 %                                                                             %
00478 %                                                                             %
00479 %                                                                             %
00480 %   G e t W a n d V i e w I t e r a t o r                                     %
00481 %                                                                             %
00482 %                                                                             %
00483 %                                                                             %
00484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00485 %
00486 %  GetWandViewIterator() iterates over the wand view in parallel and calls
00487 %  your get method for each scanline of the view.  The pixel extent is
00488 %  not confined to the image canvas-- that is you can include negative offsets
00489 %  or widths or heights that exceed the image dimension.  Any updates to
00490 %  the pixels in your callback are ignored.
00491 %
00492 %  The callback signature is:
00493 %
00494 %      MagickBooleanType GetImageViewMethod(const WandView *source,
00495 %        const ssize_t y,const int thread_id,void *context)
00496 %
00497 %  Use this pragma if the view is not single threaded:
00498 %
00499 %    #pragma omp critical
00500 %
00501 %  to define a section of code in your callback get method that must be
00502 %  executed by a single thread at a time.
00503 %
00504 %  The format of the GetWandViewIterator method is:
00505 %
00506 %      MagickBooleanType GetWandViewIterator(WandView *source,
00507 %        GetWandViewMethod get,void *context)
00508 %
00509 %  A description of each parameter follows:
00510 %
00511 %    o source: the source wand view.
00512 %
00513 %    o get: the get callback method.
00514 %
00515 %    o context: the user defined context.
00516 %
00517 */
00518 WandExport MagickBooleanType GetWandViewIterator(WandView *source,
00519   GetWandViewMethod get,void *context)
00520 {
00521   Image
00522     *source_image;
00523 
00524   MagickBooleanType
00525     status;
00526 
00527   MagickOffsetType
00528     progress;
00529 
00530   size_t
00531     height,
00532     width;
00533 
00534   ssize_t
00535     y;
00536 
00537   assert(source != (WandView *) NULL);
00538   assert(source->signature == WandSignature);
00539   if (get == (GetWandViewMethod) NULL)
00540     return(MagickFalse);
00541   source_image=source->wand->images;
00542   status=MagickTrue;
00543   progress=0;
00544   height=source->extent.height-source->extent.y;
00545   width=source->extent.width-source->extent.x;
00546 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00547   #pragma omp parallel for schedule(static) shared(progress,status) \
00548     dynamic_number_threads(source_image,width,height,1)
00549 #endif
00550   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
00551   {
00552     const int
00553       id = GetOpenMPThreadId();
00554 
00555     register const Quantum
00556       *pixels;
00557 
00558     register ssize_t
00559       x;
00560 
00561     if (status == MagickFalse)
00562       continue;
00563     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
00564       source->extent.width,1,source->exception);
00565     if (pixels == (const Quantum *) NULL)
00566       {
00567         status=MagickFalse;
00568         continue;
00569       }
00570     for (x=0; x < (ssize_t) source->extent.width; x++)
00571     {
00572       PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
00573       pixels+=GetPixelChannels(source->image);
00574     }
00575     if (get(source,y,id,context) == MagickFalse)
00576       status=MagickFalse;
00577     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
00578       {
00579         MagickBooleanType
00580           proceed;
00581 
00582 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00583         #pragma omp critical (MagickWand_GetWandViewIterator)
00584 #endif
00585         proceed=SetImageProgress(source_image,source->description,progress++,
00586           source->extent.height);
00587         if (proceed == MagickFalse)
00588           status=MagickFalse;
00589       }
00590   }
00591   return(status);
00592 }
00593 
00594 /*
00595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00596 %                                                                             %
00597 %                                                                             %
00598 %                                                                             %
00599 %   G e t W a n d V i e w P i x e l s                                         %
00600 %                                                                             %
00601 %                                                                             %
00602 %                                                                             %
00603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00604 %
00605 %  GetWandViewPixels() returns the wand view pixel_wands.
00606 %
00607 %  The format of the GetWandViewPixels method is:
00608 %
00609 %      PixelWand *GetWandViewPixels(const WandView *wand_view)
00610 %
00611 %  A description of each parameter follows:
00612 %
00613 %    o wand_view: the wand view.
00614 %
00615 */
00616 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
00617 {
00618   const int
00619     id = GetOpenMPThreadId();
00620 
00621   assert(wand_view != (WandView *) NULL);
00622   assert(wand_view->signature == WandSignature);
00623   return(wand_view->pixel_wands[id]);
00624 }
00625 
00626 /*
00627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00628 %                                                                             %
00629 %                                                                             %
00630 %                                                                             %
00631 %   G e t W a n d V i e w W a n d                                             %
00632 %                                                                             %
00633 %                                                                             %
00634 %                                                                             %
00635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00636 %
00637 %  GetWandViewWand() returns the magick wand associated with the wand view.
00638 %
00639 %  The format of the GetWandViewWand method is:
00640 %
00641 %      MagickWand *GetWandViewWand(const WandView *wand_view)
00642 %
00643 %  A description of each parameter follows:
00644 %
00645 %    o wand_view: the wand view.
00646 %
00647 */
00648 WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
00649 {
00650   assert(wand_view != (WandView *) NULL);
00651   assert(wand_view->signature == WandSignature);
00652   return(wand_view->wand);
00653 }
00654 
00655 /*
00656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00657 %                                                                             %
00658 %                                                                             %
00659 %                                                                             %
00660 %   I s W a n d V i e w                                                       %
00661 %                                                                             %
00662 %                                                                             %
00663 %                                                                             %
00664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00665 %
00666 %  IsWandView() returns MagickTrue if the the parameter is verified as a wand
00667 %  view object.
00668 %
00669 %  The format of the IsWandView method is:
00670 %
00671 %      MagickBooleanType IsWandView(const WandView *wand_view)
00672 %
00673 %  A description of each parameter follows:
00674 %
00675 %    o wand_view: the wand view.
00676 %
00677 */
00678 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
00679 {
00680   size_t
00681     length;
00682 
00683   if (wand_view == (const WandView *) NULL)
00684     return(MagickFalse);
00685   if (wand_view->signature != WandSignature)
00686     return(MagickFalse);
00687   length=strlen(WandViewId);
00688   if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
00689     return(MagickFalse);
00690   return(MagickTrue);
00691 }
00692 
00693 /*
00694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00695 %                                                                             %
00696 %                                                                             %
00697 %                                                                             %
00698 %   N e w W a n d V i e w                                                     %
00699 %                                                                             %
00700 %                                                                             %
00701 %                                                                             %
00702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00703 %
00704 %  NewWandView() returns a wand view required for all other methods in the
00705 %  Wand View API.
00706 %
00707 %  The format of the NewWandView method is:
00708 %
00709 %      WandView *NewWandView(MagickWand *wand)
00710 %
00711 %  A description of each parameter follows:
00712 %
00713 %    o wand: the wand.
00714 %
00715 */
00716 
00717 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands)
00718 {
00719   PixelWand
00720     ***pixel_wands;
00721 
00722   register ssize_t
00723     i;
00724 
00725   size_t
00726     number_threads;
00727 
00728   number_threads=GetOpenMPMaximumThreads();
00729   pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
00730     sizeof(*pixel_wands));
00731   if (pixel_wands == (PixelWand ***) NULL)
00732     return((PixelWand ***) NULL);
00733   (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
00734   for (i=0; i < (ssize_t) number_threads; i++)
00735   {
00736     pixel_wands[i]=NewPixelWands(number_wands);
00737     if (pixel_wands[i] == (PixelWand **) NULL)
00738       return(DestroyPixelsThreadSet(pixel_wands,number_wands));
00739   }
00740   return(pixel_wands);
00741 }
00742 
00743 WandExport WandView *NewWandView(MagickWand *wand)
00744 {
00745   ExceptionInfo
00746     *exception;
00747 
00748   WandView
00749     *wand_view;
00750 
00751   assert(wand != (MagickWand *) NULL);
00752   assert(wand->signature == WandSignature);
00753   wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
00754   if (wand_view == (WandView *) NULL)
00755     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00756       GetExceptionMessage(errno));
00757   (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
00758   wand_view->id=AcquireWandId();
00759   (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
00760     WandViewId,(double) wand_view->id);
00761   wand_view->description=ConstantString("WandView");
00762   wand_view->wand=wand;
00763   exception=AcquireExceptionInfo();
00764   wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
00765   wand_view->extent.width=wand->images->columns;
00766   wand_view->extent.height=wand->images->rows;
00767   wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
00768   wand_view->exception=exception;
00769   if (wand_view->pixel_wands == (PixelWand ***) NULL)
00770     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00771       GetExceptionMessage(errno));
00772   wand_view->debug=IsEventLogging();
00773   wand_view->signature=WandSignature;
00774   return(wand_view);
00775 }
00776 
00777 /*
00778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00779 %                                                                             %
00780 %                                                                             %
00781 %                                                                             %
00782 %   N e w W a n d V i e w E x t e n t                                         %
00783 %                                                                             %
00784 %                                                                             %
00785 %                                                                             %
00786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00787 %
00788 %  NewWandViewExtent() returns a wand view required for all other methods
00789 %  in the Wand View API.
00790 %
00791 %  The format of the NewWandViewExtent method is:
00792 %
00793 %      WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
00794 %        const ssize_t y,const size_t width,const size_t height)
00795 %
00796 %  A description of each parameter follows:
00797 %
00798 %    o wand: the magick wand.
00799 %
00800 %    o x,y,columns,rows:  These values define the perimeter of a extent of
00801 %      pixel_wands view.
00802 %
00803 */
00804 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
00805   const ssize_t y,const size_t width,const size_t height)
00806 {
00807   ExceptionInfo
00808     *exception;
00809 
00810   WandView
00811     *wand_view;
00812 
00813   assert(wand != (MagickWand *) NULL);
00814   assert(wand->signature == WandSignature);
00815   wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
00816   if (wand_view == (WandView *) NULL)
00817     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00818       GetExceptionMessage(errno));
00819   (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
00820   wand_view->id=AcquireWandId();
00821   (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
00822     WandViewId,(double) wand_view->id);
00823   wand_view->description=ConstantString("WandView");
00824   exception=AcquireExceptionInfo();
00825   wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
00826   wand_view->wand=wand;
00827   wand_view->extent.width=width;
00828   wand_view->extent.height=height;
00829   wand_view->extent.x=x;
00830   wand_view->extent.y=y;
00831   wand_view->exception=exception;
00832   wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
00833   if (wand_view->pixel_wands == (PixelWand ***) NULL)
00834     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00835       GetExceptionMessage(errno));
00836   wand_view->debug=IsEventLogging();
00837   wand_view->signature=WandSignature;
00838   return(wand_view);
00839 }
00840 
00841 /*
00842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00843 %                                                                             %
00844 %                                                                             %
00845 %                                                                             %
00846 %   S e t W a n d V i e w D e s c r i p t i o n                               %
00847 %                                                                             %
00848 %                                                                             %
00849 %                                                                             %
00850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00851 %
00852 %  SetWandViewDescription() associates a description with an image view.
00853 %
00854 %  The format of the SetWandViewDescription method is:
00855 %
00856 %      void SetWandViewDescription(WandView *image_view,const char *description)
00857 %
00858 %  A description of each parameter follows:
00859 %
00860 %    o wand_view: the wand view.
00861 %
00862 %    o description: the wand view description.
00863 %
00864 */
00865 MagickExport void SetWandViewDescription(WandView *wand_view,
00866   const char *description)
00867 {
00868   assert(wand_view != (WandView *) NULL);
00869   assert(wand_view->signature == WandSignature);
00870   wand_view->description=ConstantString(description);
00871 }
00872 
00873 /*
00874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00875 %                                                                             %
00876 %                                                                             %
00877 %                                                                             %
00878 %   S e t W a n d V i e w I t e r a t o r                                     %
00879 %                                                                             %
00880 %                                                                             %
00881 %                                                                             %
00882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00883 %
00884 %  SetWandViewIterator() iterates over the wand view in parallel and calls
00885 %  your set method for each scanline of the view.  The pixel extent is
00886 %  confined to the image canvas-- that is no negative offsets or widths or
00887 %  heights that exceed the image dimension.  The pixels are initiallly
00888 %  undefined and any settings you make in the callback method are automagically
00889 %  synced back to your image.
00890 %
00891 %  The callback signature is:
00892 %
00893 %      MagickBooleanType SetImageViewMethod(ImageView *destination,
00894 %        const ssize_t y,const int thread_id,void *context)
00895 %
00896 %  Use this pragma if the view is not single threaded:
00897 %
00898 %    #pragma omp critical
00899 %
00900 %  to define a section of code in your callback set method that must be
00901 %  executed by a single thread at a time.
00902 %
00903 %  The format of the SetWandViewIterator method is:
00904 %
00905 %      MagickBooleanType SetWandViewIterator(WandView *destination,
00906 %        SetWandViewMethod set,void *context)
00907 %
00908 %  A description of each parameter follows:
00909 %
00910 %    o destination: the wand view.
00911 %
00912 %    o set: the set callback method.
00913 %
00914 %    o context: the user defined context.
00915 %
00916 */
00917 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
00918   SetWandViewMethod set,void *context)
00919 {
00920   Image
00921     *destination_image;
00922 
00923   MagickBooleanType
00924     status;
00925 
00926   MagickOffsetType
00927     progress;
00928 
00929   size_t
00930     height,
00931     width;
00932 
00933   ssize_t
00934     y;
00935 
00936   assert(destination != (WandView *) NULL);
00937   assert(destination->signature == WandSignature);
00938   if (set == (SetWandViewMethod) NULL)
00939     return(MagickFalse);
00940   destination_image=destination->wand->images;
00941   status=SetImageStorageClass(destination_image,DirectClass,
00942     destination->exception);
00943   if (status == MagickFalse)
00944     return(MagickFalse);
00945   status=MagickTrue;
00946   progress=0;
00947   height=destination->extent.height-destination->extent.y;
00948   width=destination->extent.width-destination->extent.x;
00949 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00950   #pragma omp parallel for schedule(static) shared(progress,status) \
00951     dynamic_number_threads(destination_image,width,height,1)
00952 #endif
00953   for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
00954   {
00955     const int
00956       id = GetOpenMPThreadId();
00957 
00958     MagickBooleanType
00959       sync;
00960 
00961     register ssize_t
00962       x;
00963 
00964     register Quantum
00965       *restrict pixels;
00966 
00967     if (status == MagickFalse)
00968       continue;
00969     pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
00970       y,destination->extent.width,1,destination->exception);
00971     if (pixels == (Quantum *) NULL)
00972       {
00973         status=MagickFalse;
00974         continue;
00975       }
00976     if (set(destination,y,id,context) == MagickFalse)
00977       status=MagickFalse;
00978     for (x=0; x < (ssize_t) destination->extent.width; x++)
00979     {
00980       PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
00981         pixels);
00982       pixels+=GetPixelChannels(destination->image);
00983     }
00984     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
00985     if (sync == MagickFalse)
00986       status=MagickFalse;
00987     if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
00988       {
00989         MagickBooleanType
00990           proceed;
00991 
00992 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00993         #pragma omp critical (MagickWand_SetWandViewIterator)
00994 #endif
00995         proceed=SetImageProgress(destination_image,destination->description,
00996           progress++,destination->extent.height);
00997         if (proceed == MagickFalse)
00998           status=MagickFalse;
00999       }
01000   }
01001   return(status);
01002 }
01003 
01004 /*
01005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01006 %                                                                             %
01007 %                                                                             %
01008 %                                                                             %
01009 %   T r a n s f e r W a n d V i e w I t e r a t o r                           %
01010 %                                                                             %
01011 %                                                                             %
01012 %                                                                             %
01013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01014 %
01015 %  TransferWandViewIterator() iterates over two wand views in parallel and
01016 %  calls your transfer method for each scanline of the view.  The source pixel
01017 %  extent is not confined to the image canvas-- that is you can include
01018 %  negative offsets or widths or heights that exceed the image dimension.
01019 %  However, the destination wand view is confined to the image canvas-- that
01020 %  is no negative offsets or widths or heights that exceed the image dimension
01021 %  are permitted.
01022 %
01023 %  The callback signature is:
01024 %
01025 %      MagickBooleanType TransferImageViewMethod(const WandView *source,
01026 %        WandView *destination,const ssize_t y,const int thread_id,
01027 %        void *context)
01028 %
01029 %  Use this pragma if the view is not single threaded:
01030 %
01031 %    #pragma omp critical
01032 %
01033 %  to define a section of code in your callback transfer method that must be
01034 %  executed by a single thread at a time.
01035 %
01036 %  The format of the TransferWandViewIterator method is:
01037 %
01038 %      MagickBooleanType TransferWandViewIterator(WandView *source,
01039 %        WandView *destination,TransferWandViewMethod transfer,void *context)
01040 %
01041 %  A description of each parameter follows:
01042 %
01043 %    o source: the source wand view.
01044 %
01045 %    o destination: the destination wand view.
01046 %
01047 %    o transfer: the transfer callback method.
01048 %
01049 %    o context: the user defined context.
01050 %
01051 */
01052 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
01053   WandView *destination,TransferWandViewMethod transfer,void *context)
01054 {
01055   Image
01056     *destination_image,
01057     *source_image;
01058 
01059   MagickBooleanType
01060     status;
01061 
01062   MagickOffsetType
01063     progress;
01064 
01065   size_t
01066     height,
01067     width;
01068 
01069   ssize_t
01070     y;
01071 
01072   assert(source != (WandView *) NULL);
01073   assert(source->signature == WandSignature);
01074   if (transfer == (TransferWandViewMethod) NULL)
01075     return(MagickFalse);
01076   source_image=source->wand->images;
01077   destination_image=destination->wand->images;
01078   status=SetImageStorageClass(destination_image,DirectClass,
01079     destination->exception);
01080   if (status == MagickFalse)
01081     return(MagickFalse);
01082   status=MagickTrue;
01083   progress=0;
01084   height=source->extent.height-source->extent.y;
01085   width=source->extent.width-source->extent.x;
01086 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01087   #pragma omp parallel for schedule(static) shared(progress,status) \
01088     dynamic_number_threads(source_image,width,height,1)
01089 #endif
01090   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
01091   {
01092     const int
01093       id = GetOpenMPThreadId();
01094 
01095     MagickBooleanType
01096       sync;
01097 
01098     register const Quantum
01099       *restrict pixels;
01100 
01101     register ssize_t
01102       x;
01103 
01104     register Quantum
01105       *restrict destination_pixels;
01106 
01107     if (status == MagickFalse)
01108       continue;
01109     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
01110       source->extent.width,1,source->exception);
01111     if (pixels == (const Quantum *) NULL)
01112       {
01113         status=MagickFalse;
01114         continue;
01115       }
01116     for (x=0; x < (ssize_t) source->extent.width; x++)
01117     {
01118       PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
01119       pixels+=GetPixelChannels(source->image);
01120     }
01121     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
01122       destination->extent.x,y,destination->extent.width,1,
01123       destination->exception);
01124     if (destination_pixels == (Quantum *) NULL)
01125       {
01126         status=MagickFalse;
01127         continue;
01128       }
01129     for (x=0; x < (ssize_t) destination->extent.width; x++)
01130     {
01131       PixelSetQuantumPixel(destination->image,destination_pixels,
01132         destination->pixel_wands[id][x]);
01133       destination_pixels+=GetPixelChannels(destination->image);
01134     }
01135     if (transfer(source,destination,y,id,context) == MagickFalse)
01136       status=MagickFalse;
01137     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
01138       destination->extent.x,y,destination->extent.width,1,
01139       destination->exception);
01140     for (x=0; x < (ssize_t) destination->extent.width; x++)
01141     {
01142       PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
01143         destination_pixels);
01144       destination_pixels+=GetPixelChannels(destination->image);
01145     }
01146     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
01147     if (sync == MagickFalse)
01148       status=MagickFalse;
01149     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
01150       {
01151         MagickBooleanType
01152           proceed;
01153 
01154 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01155         #pragma omp critical (MagickWand_TransferWandViewIterator)
01156 #endif
01157         proceed=SetImageProgress(source_image,source->description,progress++,
01158           source->extent.height);
01159         if (proceed == MagickFalse)
01160           status=MagickFalse;
01161       }
01162   }
01163   return(status);
01164 }
01165 
01166 /*
01167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01168 %                                                                             %
01169 %                                                                             %
01170 %                                                                             %
01171 %   U p d a t e W a n d V i e w I t e r a t o r                               %
01172 %                                                                             %
01173 %                                                                             %
01174 %                                                                             %
01175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01176 %
01177 %  UpdateWandViewIterator() iterates over the wand view in parallel and calls
01178 %  your update method for each scanline of the view.  The pixel extent is
01179 %  confined to the image canvas-- that is no negative offsets or widths or
01180 %  heights that exceed the image dimension are permitted.  Updates to pixels
01181 %  in your callback are automagically synced back to the image.
01182 %
01183 %  The callback signature is:
01184 %
01185 %      MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
01186 %        const int thread_id,void *context)
01187 %
01188 %  Use this pragma if the view is not single threaded:
01189 %
01190 %    #pragma omp critical
01191 %
01192 %  to define a section of code in your callback update method that must be
01193 %  executed by a single thread at a time.
01194 %
01195 %  The format of the UpdateWandViewIterator method is:
01196 %
01197 %      MagickBooleanType UpdateWandViewIterator(WandView *source,
01198 %        UpdateWandViewMethod update,void *context)
01199 %
01200 %  A description of each parameter follows:
01201 %
01202 %    o source: the source wand view.
01203 %
01204 %    o update: the update callback method.
01205 %
01206 %    o context: the user defined context.
01207 %
01208 */
01209 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
01210   UpdateWandViewMethod update,void *context)
01211 {
01212   Image
01213     *source_image;
01214 
01215   MagickBooleanType
01216     status;
01217 
01218   MagickOffsetType
01219     progress;
01220 
01221   size_t
01222     height,
01223     width;
01224 
01225   ssize_t
01226     y;
01227 
01228   assert(source != (WandView *) NULL);
01229   assert(source->signature == WandSignature);
01230   if (update == (UpdateWandViewMethod) NULL)
01231     return(MagickFalse);
01232   source_image=source->wand->images;
01233   status=SetImageStorageClass(source_image,DirectClass,source->exception);
01234   if (status == MagickFalse)
01235     return(MagickFalse);
01236   status=MagickTrue;
01237   progress=0;
01238   height=source->extent.height-source->extent.y;
01239   width=source->extent.width-source->extent.x;
01240 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01241   #pragma omp parallel for schedule(static) shared(progress,status) \
01242     dynamic_number_threads(source_image,width,height,1)
01243 #endif
01244   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
01245   {
01246     const int
01247       id = GetOpenMPThreadId();
01248 
01249     MagickBooleanType
01250       sync;
01251 
01252     register ssize_t
01253       x;
01254 
01255     register Quantum
01256       *restrict pixels;
01257 
01258     if (status == MagickFalse)
01259       continue;
01260     pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
01261       source->extent.width,1,source->exception);
01262     if (pixels == (Quantum *) NULL)
01263       {
01264         status=MagickFalse;
01265         continue;
01266       }
01267     for (x=0; x < (ssize_t) source->extent.width; x++)
01268     {
01269       PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
01270       pixels+=GetPixelChannels(source->image);
01271     }
01272     if (update(source,y,id,context) == MagickFalse)
01273       status=MagickFalse;
01274     for (x=0; x < (ssize_t) source->extent.width; x++)
01275     {
01276       PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
01277       pixels+=GetPixelChannels(source->image);
01278     }
01279     sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
01280     if (sync == MagickFalse)
01281       status=MagickFalse;
01282     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
01283       {
01284         MagickBooleanType
01285           proceed;
01286 
01287 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01288         #pragma omp critical (MagickWand_UpdateWandViewIterator)
01289 #endif
01290         proceed=SetImageProgress(source_image,source->description,progress++,
01291           source->extent.height);
01292         if (proceed == MagickFalse)
01293           status=MagickFalse;
01294       }
01295   }
01296   return(status);
01297 }