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-2008 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 /*
00055  Define declarations.
00056 */
00057 #define PixelViewId  "PixelView"
00058 
00059 /*
00060   Typedef declarations.
00061 */
00062 struct _PixelView
00063 {
00064   unsigned long
00065     id;
00066 
00067   char
00068     name[MaxTextExtent];
00069 
00070   ExceptionInfo
00071     *exception;
00072 
00073   MagickWand
00074     *wand;
00075 
00076   ViewInfo
00077     *view;
00078 
00079   RectangleInfo
00080     region;
00081 
00082   unsigned long
00083     number_threads;
00084 
00085   PixelWand
00086     ***pixel_wands;
00087 
00088   MagickBooleanType
00089     debug;
00090 
00091   unsigned long
00092     signature;
00093 };
00094 
00095 /*
00096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00097 %                                                                             %
00098 %                                                                             %
00099 %                                                                             %
00100 %   C l o n e P i x e l V i e w                                               %
00101 %                                                                             %
00102 %                                                                             %
00103 %                                                                             %
00104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00105 %
00106 %  ClonePixelView() makes a copy of the specified pixel view.
00107 %
00108 %  The format of the ClonePixelView method is:
00109 %
00110 %      PixelView *ClonePixelView(const PixelView *pixel_view)
00111 %
00112 %  A description of each parameter follows:
00113 %
00114 %    o pixel_view: the pixel view.
00115 %
00116 */
00117 WandExport PixelView *ClonePixelView(const PixelView *pixel_view)
00118 {
00119   PixelView
00120     *clone_view;
00121 
00122   register long
00123     i;
00124 
00125   assert(pixel_view != (PixelView *) NULL);
00126   assert(pixel_view->signature == WandSignature);
00127   if (pixel_view->debug != MagickFalse)
00128     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
00129   clone_view=(PixelView *) AcquireMagickMemory(sizeof(*clone_view));
00130   if (clone_view == (PixelView *) NULL)
00131     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00132       pixel_view->name);
00133   (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
00134   clone_view->id=AcquireWandId();
00135   (void) FormatMagickString(clone_view->name,MaxTextExtent,"%s-%lu",PixelViewId,
00136     clone_view->id);
00137   clone_view->exception=AcquireExceptionInfo();
00138   InheritException(clone_view->exception,pixel_view->exception);
00139   clone_view->view=CloneCacheView(pixel_view->view);
00140   clone_view->region=pixel_view->region;
00141   clone_view->number_threads=pixel_view->number_threads;
00142   for (i=0; i < (long) pixel_view->number_threads; i++)
00143     clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
00144       pixel_view->pixel_wands[i],pixel_view->region.width);
00145   clone_view->debug=pixel_view->debug;
00146   if (clone_view->debug != MagickFalse)
00147     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
00148   clone_view->signature=WandSignature;
00149   return(clone_view);
00150 }
00151 
00152 /*
00153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00154 %                                                                             %
00155 %                                                                             %
00156 %                                                                             %
00157 %   D e s t r o y P i x e l V i e w                                           %
00158 %                                                                             %
00159 %                                                                             %
00160 %                                                                             %
00161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00162 %
00163 %  DestroyPixelView() deallocates memory associated with a pixel view.
00164 %
00165 %  The format of the DestroyPixelView method is:
00166 %
00167 %      PixelView *DestroyPixelView(PixelView *pixel_view,
00168 %        const unsigned long number_wands,const unsigned long number_threads)
00169 %
00170 %  A description of each parameter follows:
00171 %
00172 %    o pixel_view: the pixel view.
00173 %
00174 %    o number_wand: the number of pixel wands.
00175 %
00176 %    o number_threads: number of threads.
00177 %
00178 */
00179 
00180 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
00181   const unsigned long number_wands,const unsigned long number_threads)
00182 {
00183   register long
00184     i;
00185 
00186   assert(pixel_wands != (PixelWand ***) NULL);
00187   for (i=0; i < (long) number_threads; i++)
00188     if (pixel_wands[i] != (PixelWand **) NULL)
00189       pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
00190   return((PixelWand ***) RelinquishMagickMemory(pixel_wands));
00191 }
00192 
00193 WandExport PixelView *DestroyPixelView(PixelView *pixel_view)
00194 {
00195   assert(pixel_view != (PixelView *) NULL);
00196   assert(pixel_view->signature == WandSignature);
00197   pixel_view->pixel_wands=DestroyPixelsThreadSet(pixel_view->pixel_wands,
00198     pixel_view->region.width,pixel_view->number_threads);
00199   pixel_view->view=DestroyCacheView(pixel_view->view);
00200   pixel_view->exception=DestroyExceptionInfo(pixel_view->exception);
00201   pixel_view->signature=(~WandSignature);
00202   RelinquishWandId(pixel_view->id);
00203   pixel_view=(PixelView *) RelinquishMagickMemory(pixel_view);
00204   return(pixel_view);
00205 }
00206 
00207 /*
00208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00209 %                                                                             %
00210 %                                                                             %
00211 %                                                                             %
00212 %   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             %
00213 %                                                                             %
00214 %                                                                             %
00215 %                                                                             %
00216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00217 %
00218 %  DuplexTransferPixelViewIterator() iterates over three pixel views in
00219 %  parallel and calls your transfer method for each scanline of the view.  The
00220 %  source and duplex pixel region 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 pixel 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 %  Use this pragma:
00227 %
00228 %    #pragma omp critical
00229 %
00230 %  to define a section of code in your callback transfer method that must be
00231 %  executed by a single thread at a time.
00232 %
00233 %  The format of the DuplexTransferPixelViewIterator method is:
00234 %
00235 %      MagickBooleanType DuplexTransferPixelViewIterator(PixelView *source,
00236 %        PixelView *duplex,PixelView *destination,
00237 %        DuplexTransferPixelViewMethod transfer,void *context)
00238 %
00239 %  A description of each parameter follows:
00240 %
00241 %    o source: the source pixel view.
00242 %
00243 %    o duplex: the duplex pixel view.
00244 %
00245 %    o destination: the destination pixel view.
00246 %
00247 %    o transfer: the transfer callback method.
00248 %
00249 %    o context: the user defined context.
00250 %
00251 */
00252 WandExport MagickBooleanType DuplexTransferPixelViewIterator(
00253   PixelView *source,PixelView *duplex,PixelView *destination,
00254   DuplexTransferPixelViewMethod transfer,void *context)
00255 {
00256 #define DuplexTransferPixelViewTag  "PixelView/DuplexTransfer"
00257 
00258   ExceptionInfo
00259     *exception;
00260 
00261   Image
00262     *destination_image,
00263     *duplex_image,
00264     *source_image;
00265 
00266   long
00267     progress,
00268     y;
00269 
00270   MagickBooleanType
00271     status;
00272 
00273   assert(source != (PixelView *) NULL);
00274   assert(source->signature == WandSignature);
00275   if (transfer == (DuplexTransferPixelViewMethod) NULL)
00276     return(MagickFalse);
00277   source_image=source->wand->images;
00278   duplex_image=duplex->wand->images;
00279   destination_image=destination->wand->images;
00280   if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
00281     return(MagickFalse);
00282   status=MagickTrue;
00283   progress=0;
00284   exception=destination->exception;
00285 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00286   #pragma omp parallel for schedule(dynamic) shared(progress,status)
00287 #endif
00288   for (y=source->region.y; y < (long) source->region.height; y++)
00289   {
00290     MagickBooleanType
00291       sync;
00292 
00293     register const IndexPacket
00294       *duplex_indexes,
00295       *indexes;
00296 
00297     register const PixelPacket
00298       *duplex_pixels,
00299       *pixels;
00300 
00301     register IndexPacket
00302       *destination_indexes;
00303 
00304     register long
00305       id,
00306       x;
00307 
00308     register PixelPacket
00309       *destination_pixels;
00310 
00311     if (status == MagickFalse)
00312       continue;
00313     id=GetPixelCacheThreadId();
00314     pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
00315       source->region.width,1,source->exception);
00316     if (pixels == (const PixelPacket *) NULL)
00317       {
00318         status=MagickFalse;
00319         continue;
00320       }
00321     indexes=GetCacheViewVirtualIndexQueue(source->view);
00322     for (x=0; x < (long) source->region.width; x++)
00323       PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
00324     if (source_image->colorspace == CMYKColorspace)
00325       for (x=0; x < (long) source->region.width; x++)
00326         PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
00327     if (source_image->storage_class == PseudoClass)
00328       for (x=0; x < (long) source->region.width; x++)
00329         PixelSetIndex(source->pixel_wands[id][x],indexes[x]);
00330     duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->region.x,y,
00331       duplex->region.width,1,duplex->exception);
00332     if (duplex_pixels == (const PixelPacket *) NULL)
00333       {
00334         status=MagickFalse;
00335         continue;
00336       }
00337     duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
00338     for (x=0; x < (long) duplex->region.width; x++)
00339       PixelSetQuantumColor(duplex->pixel_wands[id][x],duplex_pixels+x);
00340     if (duplex_image->colorspace == CMYKColorspace)
00341       for (x=0; x < (long) duplex->region.width; x++)
00342         PixelSetBlackQuantum(duplex->pixel_wands[id][x],duplex_indexes[x]);
00343     if (duplex_image->storage_class == PseudoClass)
00344       for (x=0; x < (long) duplex->region.width; x++)
00345         PixelSetIndex(duplex->pixel_wands[id][x],duplex_indexes[x]);
00346     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
00347       destination->region.x,y,destination->region.width,1,exception);
00348     if (destination_pixels == (PixelPacket *) NULL)
00349       {
00350         status=MagickFalse;
00351         continue;
00352       }
00353     destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
00354     for (x=0; x < (long) destination->region.width; x++)
00355       PixelSetQuantumColor(destination->pixel_wands[id][x],
00356         destination_pixels+x);
00357     if (destination_image->colorspace == CMYKColorspace)
00358       for (x=0; x < (long) destination->region.width; x++)
00359         PixelSetBlackQuantum(destination->pixel_wands[id][x],
00360           destination_indexes[x]);
00361     if (destination_image->storage_class == PseudoClass)
00362       for (x=0; x < (long) destination->region.width; x++)
00363         PixelSetIndex(destination->pixel_wands[id][x],destination_indexes[x]);
00364     if (transfer(source,duplex,destination,context) == MagickFalse)
00365       status=MagickFalse;
00366     for (x=0; x < (long) destination->region.width; x++)
00367       PixelGetQuantumColor(destination->pixel_wands[id][x],
00368         destination_pixels+x);
00369     if (destination_image->colorspace == CMYKColorspace)
00370       for (x=0; x < (long) destination->region.width; x++)
00371         destination_indexes[x]=PixelGetBlackQuantum(
00372           destination->pixel_wands[id][x]);
00373     sync=SyncCacheViewAuthenticPixels(destination->view,exception);
00374     if (sync == MagickFalse)
00375       {
00376         InheritException(destination->exception,GetCacheViewException(
00377           source->view));
00378         status=MagickFalse;
00379       }
00380     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
00381       {
00382         MagickBooleanType
00383           proceed;
00384 
00385 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00386   #pragma omp critical
00387 #endif
00388         proceed=SetImageProgress(source_image,DuplexTransferPixelViewTag,
00389           progress++,source->region.height);
00390         if (proceed == MagickFalse)
00391           status=MagickFalse;
00392       }
00393   }
00394   return(status);
00395 }
00396 
00397 /*
00398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00399 %                                                                             %
00400 %                                                                             %
00401 %                                                                             %
00402 %   G e t P i x e l V i e w E x c e p t i o n                                 %
00403 %                                                                             %
00404 %                                                                             %
00405 %                                                                             %
00406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00407 %
00408 %  GetPixelViewException() returns the severity, reason, and description of any
00409 %  error that occurs when utilizing a pixel view.
00410 %
00411 %  The format of the GetPixelViewException method is:
00412 %
00413 %      char *GetPixelViewException(const PixelWand *pixel_view,
00414 %        ExceptionType *severity)
00415 %
00416 %  A description of each parameter follows:
00417 %
00418 %    o pixel_view: the pixel pixel_view.
00419 %
00420 %    o severity: the severity of the error is returned here.
00421 %
00422 */
00423 WandExport char *GetPixelViewException(const PixelView *pixel_view,
00424   ExceptionType *severity)
00425 {
00426   char
00427     *description;
00428 
00429   assert(pixel_view != (const PixelView *) NULL);
00430   assert(pixel_view->signature == WandSignature);
00431   if (pixel_view->debug != MagickFalse)
00432     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",pixel_view->name);
00433   assert(severity != (ExceptionType *) NULL);
00434   *severity=pixel_view->exception->severity;
00435   description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
00436     sizeof(*description));
00437   if (description == (char *) NULL)
00438     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00439       pixel_view->name);
00440   *description='\0';
00441   if (pixel_view->exception->reason != (char *) NULL)
00442     (void) CopyMagickString(description,GetLocaleExceptionMessage(
00443       pixel_view->exception->severity,pixel_view->exception->reason),
00444         MaxTextExtent);
00445   if (pixel_view->exception->description != (char *) NULL)
00446     {
00447       (void) ConcatenateMagickString(description," (",MaxTextExtent);
00448       (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
00449         pixel_view->exception->severity,pixel_view->exception->description),
00450         MaxTextExtent);
00451       (void) ConcatenateMagickString(description,")",MaxTextExtent);
00452     }
00453   return(description);
00454 }
00455 
00456 /*
00457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00458 %                                                                             %
00459 %                                                                             %
00460 %                                                                             %
00461 %   G e t P i x e l V i e w H e i g h t                                       %
00462 %                                                                             %
00463 %                                                                             %
00464 %                                                                             %
00465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00466 %
00467 %  GetPixelViewHeight() returns the pixel view height.
00468 %
00469 %  The format of the GetPixelViewHeight method is:
00470 %
00471 %      unsigned long GetPixelViewHeight(const PixelView *pixel_view)
00472 %
00473 %  A description of each parameter follows:
00474 %
00475 %    o pixel_view: the pixel view.
00476 %
00477 */
00478 WandExport unsigned long GetPixelViewHeight(const PixelView *pixel_view)
00479 {
00480   assert(pixel_view != (PixelView *) NULL);
00481   assert(pixel_view->signature == WandSignature);
00482   return(pixel_view->region.height);
00483 }
00484 
00485 /*
00486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00487 %                                                                             %
00488 %                                                                             %
00489 %                                                                             %
00490 %   G e t P i x e l V i e w I t e r a t o r                                   %
00491 %                                                                             %
00492 %                                                                             %
00493 %                                                                             %
00494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00495 %
00496 %  GetPixelViewIterator() iterates over the pixel view in parallel and calls
00497 %  your get method for each scanline of the view.  The pixel region is
00498 %  not confined to the image canvas-- that is you can include negative offsets
00499 %  or widths or heights that exceed the image dimension.  Any updates to
00500 %  the pixels in your callback are ignored.
00501 %
00502 %  Use this pragma:
00503 %
00504 %    #pragma omp critical
00505 %
00506 %  to define a section of code in your callback get method that must be
00507 %  executed by a single thread at a time.
00508 %
00509 %  The format of the GetPixelViewIterator method is:
00510 %
00511 %      MagickBooleanType GetPixelViewIterator(PixelView *source,
00512 %        GetPixelViewMethod get,void *context)
00513 %
00514 %  A description of each parameter follows:
00515 %
00516 %    o source: the source pixel view.
00517 %
00518 %    o get: the get callback method.
00519 %
00520 %    o context: the user defined context.
00521 %
00522 */
00523 WandExport MagickBooleanType GetPixelViewIterator(PixelView *source,
00524   GetPixelViewMethod get,void *context)
00525 {
00526 #define GetPixelViewTag  "PixelView/Get"
00527 
00528   Image
00529     *source_image;
00530 
00531   long
00532     progress,
00533     y;
00534 
00535   MagickBooleanType
00536     status;
00537 
00538   assert(source != (PixelView *) NULL);
00539   assert(source->signature == WandSignature);
00540   if (get == (GetPixelViewMethod) NULL)
00541     return(MagickFalse);
00542   source_image=source->wand->images;
00543   status=MagickTrue;
00544   progress=0;
00545 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00546   #pragma omp parallel for schedule(dynamic) shared(progress,status)
00547 #endif
00548   for (y=source->region.y; y < (long) source->region.height; y++)
00549   {
00550     register const IndexPacket
00551       *indexes;
00552 
00553     register const PixelPacket
00554       *pixels;
00555 
00556     register long
00557       id,
00558       x;
00559 
00560     if (status == MagickFalse)
00561       continue;
00562     id=GetPixelCacheThreadId();
00563     pixels=GetCacheViewVirtualPixels(source->view,source->region.x,y,
00564       source->region.width,1,source->exception);
00565     if (pixels == (const PixelPacket *) NULL)
00566       {
00567         status=MagickFalse;
00568         continue;
00569       }
00570     indexes=GetCacheViewVirtualIndexQueue(source->view);
00571     for (x=0; x < (long) source->region.width; x++)
00572       PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
00573     if (source_image->colorspace == CMYKColorspace)
00574       for (x=0; x < (long) source->region.width; x++)
00575         PixelSetBlackQuantum(source->pixel_wands[id][x],indexes[x]);
00576     if (source_image->storage_class == PseudoClass)
00577       for (x=0; x < (long) source->region.width; x++)
00578         PixelSetIndex(source->pixel_wands[id][x],indexes[x]);
00579     if (get(source,context) == MagickFalse)
00580       status=MagickFalse;
00581     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
00582       {
00583         MagickBooleanType
00584           proceed;
00585 
00586 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00587   #pragma omp critical
00588 #endif
00589         proceed=SetImageProgress(source_image,GetPixelViewTag,progress++,
00590           source->region.height);
00591         if (proceed == MagickFalse)
00592           status=MagickFalse;
00593       }
00594   }
00595   return(status);
00596 }
00597 
00598 /*
00599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00600 %                                                                             %
00601 %                                                                             %
00602 %                                                                             %
00603 %   G e t P i x e l V i e w P i x e l s                                       %
00604 %                                                                             %
00605 %                                                                             %
00606 %                                                                             %
00607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00608 %
00609 %  GetPixelViewPixels() returns the pixel view pixel_wands.
00610 %
00611 %  The format of the GetPixelViewPixels method is:
00612 %
00613 %      PixelWand *GetPixelViewPixels(const PixelView *pixel_view)
00614 %
00615 %  A description of each parameter follows:
00616 %
00617 %    o pixel_view: the pixel view.
00618 %
00619 */
00620 WandExport PixelWand **GetPixelViewPixels(const PixelView *pixel_view)
00621 {
00622   long
00623     id;
00624 
00625   assert(pixel_view != (PixelView *) NULL);
00626   assert(pixel_view->signature == WandSignature);
00627   id=GetPixelCacheThreadId();
00628   return(pixel_view->pixel_wands[id]);
00629 }
00630 
00631 /*
00632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00633 %                                                                             %
00634 %                                                                             %
00635 %                                                                             %
00636 %   G e t P i x e l V i e w W a n d                                           %
00637 %                                                                             %
00638 %                                                                             %
00639 %                                                                             %
00640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00641 %
00642 %  GetPixelViewWand() returns the magick wand associated with the pixel view.
00643 %
00644 %  The format of the GetPixelViewWand method is:
00645 %
00646 %      MagickWand *GetPixelViewWand(const PixelView *pixel_view)
00647 %
00648 %  A description of each parameter follows:
00649 %
00650 %    o pixel_view: the pixel view.
00651 %
00652 */
00653 WandExport MagickWand *GetPixelViewWand(const PixelView *pixel_view)
00654 {
00655   assert(pixel_view != (PixelView *) NULL);
00656   assert(pixel_view->signature == WandSignature);
00657   return(pixel_view->wand);
00658 }
00659 
00660 /*
00661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00662 %                                                                             %
00663 %                                                                             %
00664 %                                                                             %
00665 %   G e t P i x e l V i e w W i d t h                                         %
00666 %                                                                             %
00667 %                                                                             %
00668 %                                                                             %
00669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00670 %
00671 %  GetPixelViewWidth() returns the pixel view width.
00672 %
00673 %  The format of the GetPixelViewWidth method is:
00674 %
00675 %      unsigned long GetPixelViewWidth(const PixelView *pixel_view)
00676 %
00677 %  A description of each parameter follows:
00678 %
00679 %    o pixel_view: the pixel view.
00680 %
00681 */
00682 WandExport unsigned long GetPixelViewWidth(const PixelView *pixel_view)
00683 {
00684   assert(pixel_view != (PixelView *) NULL);
00685   assert(pixel_view->signature == WandSignature);
00686   return(pixel_view->region.width);
00687 }
00688 
00689 /*
00690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00691 %                                                                             %
00692 %                                                                             %
00693 %                                                                             %
00694 %   G e t P i x e l V i e w X                                                 %
00695 %                                                                             %
00696 %                                                                             %
00697 %                                                                             %
00698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00699 %
00700 %  GetPixelViewX() returns the pixel view x offset.
00701 %
00702 %  The format of the GetPixelViewX method is:
00703 %
00704 %      long GetPixelViewX(const PixelView *pixel_view)
00705 %
00706 %  A description of each parameter follows:
00707 %
00708 %    o pixel_view: the pixel view.
00709 %
00710 */
00711 WandExport long GetPixelViewX(const PixelView *pixel_view)
00712 {
00713   assert(pixel_view != (PixelView *) NULL);
00714   assert(pixel_view->signature == WandSignature);
00715   return(pixel_view->region.x);
00716 }
00717 
00718 /*
00719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00720 %                                                                             %
00721 %                                                                             %
00722 %                                                                             %
00723 %   G e t P i x e l V i e w Y                                                 %
00724 %                                                                             %
00725 %                                                                             %
00726 %                                                                             %
00727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00728 %
00729 %  GetPixelViewY() returns the pixel view y offset.
00730 %
00731 %  The format of the GetPixelViewY method is:
00732 %
00733 %      long GetPixelViewY(const PixelView *pixel_view)
00734 %
00735 %  A description of each parameter follows:
00736 %
00737 %    o pixel_view: the pixel view.
00738 %
00739 */
00740 WandExport long GetPixelViewY(const PixelView *pixel_view)
00741 {
00742   assert(pixel_view != (PixelView *) NULL);
00743   assert(pixel_view->signature == WandSignature);
00744   return(pixel_view->region.y);
00745 }
00746 
00747 /*
00748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00749 %                                                                             %
00750 %                                                                             %
00751 %                                                                             %
00752 %   I s P i x e l V i e w                                                     %
00753 %                                                                             %
00754 %                                                                             %
00755 %                                                                             %
00756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00757 %
00758 %  IsPixelView() returns MagickTrue if the the parameter is verified as a pixel
00759 %  view container.
00760 %
00761 %  The format of the IsPixelView method is:
00762 %
00763 %      MagickBooleanType IsPixelView(const PixelView *pixel_view)
00764 %
00765 %  A description of each parameter follows:
00766 %
00767 %    o pixel_view: the pixel view.
00768 %
00769 */
00770 WandExport MagickBooleanType IsPixelView(const PixelView *pixel_view)
00771 {
00772   size_t
00773     length;
00774 
00775   if (pixel_view == (const PixelView *) NULL)
00776     return(MagickFalse);
00777   if (pixel_view->signature != WandSignature)
00778     return(MagickFalse);
00779   length=strlen(PixelViewId);
00780   if (LocaleNCompare(pixel_view->name,PixelViewId,length) != 0)
00781     return(MagickFalse);
00782   return(MagickTrue);
00783 }
00784 
00785 /*
00786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00787 %                                                                             %
00788 %                                                                             %
00789 %                                                                             %
00790 %   N e w P i x e l V i e w                                                   %
00791 %                                                                             %
00792 %                                                                             %
00793 %                                                                             %
00794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00795 %
00796 %  NewPixelView() returns a pixel view required for all other methods in the
00797 %  Pixel View API.
00798 %
00799 %  The format of the NewPixelView method is:
00800 %
00801 %      PixelView *NewPixelView(MagickWand *wand)
00802 %
00803 %  A description of each parameter follows:
00804 %
00805 %    o wand: the wand.
00806 %
00807 */
00808 
00809 static PixelWand ***AcquirePixelsThreadSet(const unsigned long number_wands,
00810   const unsigned long number_threads)
00811 {
00812   PixelWand
00813     ***pixel_wands;
00814 
00815   register long
00816     i;
00817 
00818   pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
00819     sizeof(*pixel_wands));
00820   if (pixel_wands == (PixelWand ***) NULL)
00821     return((PixelWand ***) NULL);
00822   (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
00823   for (i=0; i < (long) number_threads; i++)
00824   {
00825     pixel_wands[i]=NewPixelWands(number_wands);
00826     if (pixel_wands[i] == (PixelWand **) NULL)
00827       return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
00828   }
00829   return(pixel_wands);
00830 }
00831 
00832 WandExport PixelView *NewPixelView(MagickWand *wand)
00833 {
00834   PixelView
00835     *pixel_view;
00836 
00837   assert(wand != (MagickWand *) NULL);
00838   assert(wand->signature == MagickSignature);
00839   pixel_view=(PixelView *) AcquireMagickMemory(sizeof(*pixel_view));
00840   if (pixel_view == (PixelView *) NULL)
00841     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00842       strerror(errno));
00843   (void) ResetMagickMemory(pixel_view,0,sizeof(*pixel_view));
00844   pixel_view->id=AcquireWandId();
00845   (void) FormatMagickString(pixel_view->name,MaxTextExtent,"%s-%lu",
00846     PixelViewId,pixel_view->id);
00847   pixel_view->exception=AcquireExceptionInfo();
00848   pixel_view->wand=wand;
00849   pixel_view->view=AcquireCacheView(pixel_view->wand->images);
00850   pixel_view->region.width=wand->images->columns;
00851   pixel_view->region.height=wand->images->rows;
00852   pixel_view->number_threads=GetPixelCacheMaximumThreads();
00853   pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
00854     pixel_view->number_threads);
00855   if (pixel_view->pixel_wands == (PixelWand ***) NULL)
00856     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00857       strerror(errno));
00858   pixel_view->debug=IsEventLogging();
00859   pixel_view->signature=WandSignature;
00860   return(pixel_view);
00861 }
00862 
00863 /*
00864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00865 %                                                                             %
00866 %                                                                             %
00867 %                                                                             %
00868 %   N e w P i x e l V i e w R e g i o n                                       %
00869 %                                                                             %
00870 %                                                                             %
00871 %                                                                             %
00872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00873 %
00874 %  NewPixelViewRegion() returns a pixel view required for all other methods
00875 %  in the Pixel View API.
00876 %
00877 %  The format of the NewPixelViewRegion method is:
00878 %
00879 %      PixelView *NewPixelViewRegion(MagickWand *wand,const long x,
00880 %        const long y,const unsigned long width,const unsigned long height)
00881 %
00882 %  A description of each parameter follows:
00883 %
00884 %    o wand: the magick wand.
00885 %
00886 %    o x,y,columns,rows:  These values define the perimeter of a region of
00887 %      pixel_wands view.
00888 %
00889 */
00890 WandExport PixelView *NewPixelViewRegion(MagickWand *wand,const long x,
00891   const long y,const unsigned long width,const unsigned long height)
00892 {
00893   PixelView
00894     *pixel_view;
00895 
00896   assert(wand != (MagickWand *) NULL);
00897   assert(wand->signature == MagickSignature);
00898   pixel_view=(PixelView *) AcquireMagickMemory(sizeof(*pixel_view));
00899   if (pixel_view == (PixelView *) NULL)
00900     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00901       strerror(errno));
00902   (void) ResetMagickMemory(pixel_view,0,sizeof(*pixel_view));
00903   pixel_view->id=AcquireWandId();
00904   (void) FormatMagickString(pixel_view->name,MaxTextExtent,"%s-%lu",
00905     PixelViewId,pixel_view->id);
00906   pixel_view->exception=AcquireExceptionInfo();
00907   pixel_view->view=AcquireCacheView(pixel_view->wand->images);
00908   pixel_view->wand=wand;
00909   pixel_view->region.width=width;
00910   pixel_view->region.height=height;
00911   pixel_view->region.x=x;
00912   pixel_view->region.y=y;
00913   pixel_view->number_threads=GetPixelCacheMaximumThreads();
00914   pixel_view->pixel_wands=AcquirePixelsThreadSet(pixel_view->region.width,
00915     pixel_view->number_threads);
00916   if (pixel_view->pixel_wands == (PixelWand ***) NULL)
00917     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
00918       strerror(errno));
00919   pixel_view->debug=IsEventLogging();
00920   pixel_view->signature=WandSignature;
00921   return(pixel_view);
00922 }
00923 
00924 /*
00925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00926 %                                                                             %
00927 %                                                                             %
00928 %                                                                             %
00929 %   S e t P i x e l V i e w I t e r a t o r                                   %
00930 %                                                                             %
00931 %                                                                             %
00932 %                                                                             %
00933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00934 %
00935 %  SetPixelViewIterator() iterates over the pixel view in parallel and calls
00936 %  your set method for each scanline of the view.  The pixel region is
00937 %  confined to the image canvas-- that is no negative offsets or widths or
00938 %  heights that exceed the image dimension.  The pixels are initiallly
00939 %  undefined and any settings you make in the callback method are automagically
00940 %  synced back to your image.
00941 %
00942 %  Use this pragma:
00943 %
00944 %    #pragma omp critical
00945 %
00946 %  to define a section of code in your callback set method that must be
00947 %  executed by a single thread at a time.
00948 %
00949 %  The format of the SetPixelViewIterator method is:
00950 %
00951 %      MagickBooleanType SetPixelViewIterator(PixelView *destination,
00952 %        SetPixelViewMethod set,void *context)
00953 %
00954 %  A description of each parameter follows:
00955 %
00956 %    o destination: the pixel view.
00957 %
00958 %    o set: the set callback method.
00959 %
00960 %    o context: the user defined context.
00961 %
00962 */
00963 WandExport MagickBooleanType SetPixelViewIterator(PixelView *destination,
00964   SetPixelViewMethod set,void *context)
00965 {
00966 #define SetPixelViewTag  "PixelView/Set"
00967 
00968   ExceptionInfo
00969     *exception;
00970 
00971   Image
00972     *destination_image;
00973 
00974   long
00975     progress,
00976     y;
00977 
00978   MagickBooleanType
00979     status;
00980 
00981   assert(destination != (PixelView *) NULL);
00982   assert(destination->signature == WandSignature);
00983   if (set == (SetPixelViewMethod) NULL)
00984     return(MagickFalse);
00985   destination_image=destination->wand->images;
00986   if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
00987     return(MagickFalse);
00988   status=MagickTrue;
00989   progress=0;
00990   exception=destination->exception;
00991 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00992   #pragma omp parallel for schedule(dynamic) shared(progress,status)
00993 #endif
00994   for (y=destination->region.y; y < (long) destination->region.height; y++)
00995   {
00996     MagickBooleanType
00997       sync;
00998 
00999     register IndexPacket
01000       *indexes;
01001 
01002     register long
01003       id,
01004       x;
01005 
01006     register PixelPacket
01007       *pixels;
01008 
01009     if (status == MagickFalse)
01010       continue;
01011     id=GetPixelCacheThreadId();
01012     pixels=GetCacheViewAuthenticPixels(destination->view,destination->region.x,
01013       y,destination->region.width,1,exception);
01014     if (pixels == (PixelPacket *) NULL)
01015       {
01016         InheritException(destination->exception,GetCacheViewException(
01017           destination->view));
01018         status=MagickFalse;
01019         continue;
01020       }
01021     indexes=GetCacheViewAuthenticIndexQueue(destination->view);
01022     if (set(destination,context) == MagickFalse)
01023       status=MagickFalse;
01024     for (x=0; x < (long) destination->region.width; x++)
01025       PixelGetQuantumColor(destination->pixel_wands[id][x],pixels+x);
01026     if (destination_image->colorspace == CMYKColorspace)
01027       for (x=0; x < (long) destination->region.width; x++)
01028         indexes[x]=PixelGetBlackQuantum(destination->pixel_wands[id][x]);
01029     sync=SyncCacheViewAuthenticPixels(destination->view,exception);
01030     if (sync == MagickFalse)
01031       {
01032         InheritException(destination->exception,GetCacheViewException(
01033           destination->view));
01034         status=MagickFalse;
01035       }
01036     if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
01037       {
01038         MagickBooleanType
01039           proceed;
01040 
01041 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01042   #pragma omp critical
01043 #endif
01044         proceed=SetImageProgress(destination_image,SetPixelViewTag,progress++,
01045           destination->region.height);
01046         if (proceed == MagickFalse)
01047           status=MagickFalse;
01048       }
01049   }
01050   return(status);
01051 }
01052 
01053 /*
01054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01055 %                                                                             %
01056 %                                                                             %
01057 %                                                                             %
01058 %   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                         %
01059 %                                                                             %
01060 %                                                                             %
01061 %                                                                             %
01062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01063 %
01064 %  TransferPixelViewIterator() iterates over two pixel views in parallel and
01065 %  calls your transfer method for each scanline of the view.  The source pixel
01066 %  region is not confined to the image canvas-- that is you can include
01067 %  negative offsets or widths or heights that exceed the image dimension.
01068 %  However, the destination pixel view is confined to the image canvas-- that
01069 %  is no negative offsets or widths or heights that exceed the image dimension
01070 %  are permitted.
01071 %
01072 %  Use this pragma:
01073 %
01074 %    #pragma omp critical
01075 %
01076 %  to define a section of code in your callback transfer method that must be
01077 %  executed by a single thread at a time.
01078 %
01079 %  The format of the TransferPixelViewIterator method is:
01080 %
01081 %      MagickBooleanType TransferPixelViewIterator(PixelView *source,
01082 %        PixelView *destination,TransferPixelViewMethod transfer,void *context)
01083 %
01084 %  A description of each parameter follows:
01085 %
01086 %    o source: the source pixel view.
01087 %
01088 %    o destination: the destination pixel view.
01089 %
01090 %    o transfer: the transfer callback method.
01091 %
01092 %    o context: the user defined context.
01093 %
01094 */
01095 WandExport MagickBooleanType TransferPixelViewIterator(PixelView *source,
01096   PixelView *destination,TransferPixelViewMethod transfer,void *context)
01097 {
01098 #define TransferPixelViewTag  "PixelView/Transfer"
01099 
01100   ExceptionInfo
01101     *exception;
01102 
01103   Image
01104     *destination_image,
01105     *source_image;
01106 
01107   long
01108     progress,
01109     y;
01110 
01111   MagickBooleanType
01112     status;
01113 
01114   assert(source != (PixelView *) NULL);
01115   assert(source->signature == WandSignature);
01116   if (transfer == (TransferPixelViewMethod) NULL)
01117     return(MagickFalse);
01118   source_image=source->wand->images;
01119   destination_image=destination->wand->images;
01120   if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
01121     return(MagickFalse);
01122   status=MagickTrue;
01123   progress=0;
01124   exception=destination->exception;
01125 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01126   #pragma omp parallel for schedule(dynamic) shared(progress,status)
01127 #endif
01128   for (y=source-&