pixel-view.c

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