Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                     IIIII  M   M   AAA    GGGG  EEEEE                       %
      6 %                       I    MM MM  A   A  G      E                           %
      7 %                       I    M M M  AAAAA  G  GG  EEE                         %
      8 %                       I    M   M  A   A  G   G  E                           %
      9 %                     IIIII  M   M  A   A   GGGG  EEEEE                       %
     10 %                                                                             %
     11 %                         V   V  IIIII  EEEEE  W   W                          %
     12 %                         V   V    I    E      W   W                          %
     13 %                         V   V    I    EEE    W W W                          %
     14 %                          V V     I    E      WW WW                          %
     15 %                           V    IIIII  EEEEE  W   W                          %
     16 %                                                                             %
     17 %                                                                             %
     18 %                       MagickCore Image View Methods                         %
     19 %                                                                             %
     20 %                              Software Design                                %
     21 %                                   Cristy                                    %
     22 %                                March 2003                                   %
     23 %                                                                             %
     24 %                                                                             %
     25 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     26 %  dedicated to making software imaging solutions freely available.           %
     27 %                                                                             %
     28 %  You may not use this file except in compliance with the License.  You may  %
     29 %  obtain a copy of the License at                                            %
     30 %                                                                             %
     31 %    http://www.imagemagick.org/script/license.php                            %
     32 %                                                                             %
     33 %  Unless required by applicable law or agreed to in writing, software        %
     34 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     35 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     36 %  See the License for the specific language governing permissions and        %
     37 %  limitations under the License.                                             %
     38 %                                                                             %
     39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     40 %
     41 %
     42 %
     43 */
     44 
     45 /*
     47   Include declarations.
     48 */
     49 #include "MagickCore/studio.h"
     50 #include "MagickCore/MagickCore.h"
     51 #include "MagickCore/exception-private.h"
     52 #include "MagickCore/monitor-private.h"
     53 #include "MagickCore/thread-private.h"
     54 
     55 /*
     57   Typedef declarations.
     58 */
     59 struct _ImageView
     60 {
     61   char
     62     *description;
     63 
     64   RectangleInfo
     65     extent;
     66 
     67   Image
     68     *image;
     69 
     70   CacheView
     71     *view;
     72 
     73   ExceptionInfo
     74     *exception;
     75 
     76   MagickBooleanType
     77     debug;
     78 
     79   size_t
     80     signature;
     81 };
     82 
     83 /*
     85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     86 %                                                                             %
     87 %                                                                             %
     88 %                                                                             %
     89 %   C l o n e I m a g e V i e w                                               %
     90 %                                                                             %
     91 %                                                                             %
     92 %                                                                             %
     93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     94 %
     95 %  CloneImageView() makes a copy of the specified image view.
     96 %
     97 %  The format of the CloneImageView method is:
     98 %
     99 %      ImageView *CloneImageView(const ImageView *image_view)
    100 %
    101 %  A description of each parameter follows:
    102 %
    103 %    o image_view: the image view.
    104 %
    105 */
    106 MagickExport ImageView *CloneImageView(const ImageView *image_view)
    107 {
    108   ImageView
    109     *clone_view;
    110 
    111   assert(image_view != (ImageView *) NULL);
    112   assert(image_view->signature == MagickCoreSignature);
    113   clone_view=(ImageView *) AcquireMagickMemory(sizeof(*clone_view));
    114   if (clone_view == (ImageView *) NULL)
    115     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    116   (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
    117   clone_view->description=ConstantString(image_view->description);
    118   clone_view->extent=image_view->extent;
    119   clone_view->view=CloneCacheView(image_view->view);
    120   clone_view->exception=AcquireExceptionInfo();
    121   InheritException(clone_view->exception,image_view->exception);
    122   clone_view->debug=image_view->debug;
    123   clone_view->signature=MagickCoreSignature;
    124   return(clone_view);
    125 }
    126 
    127 /*
    129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    130 %                                                                             %
    131 %                                                                             %
    132 %                                                                             %
    133 %   D e s t r o y I m a g e V i e w                                           %
    134 %                                                                             %
    135 %                                                                             %
    136 %                                                                             %
    137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    138 %
    139 %  DestroyImageView() deallocates memory associated with a image view.
    140 %
    141 %  The format of the DestroyImageView method is:
    142 %
    143 %      ImageView *DestroyImageView(ImageView *image_view)
    144 %
    145 %  A description of each parameter follows:
    146 %
    147 %    o image_view: the image view.
    148 %
    149 */
    150 MagickExport ImageView *DestroyImageView(ImageView *image_view)
    151 {
    152   assert(image_view != (ImageView *) NULL);
    153   assert(image_view->signature == MagickCoreSignature);
    154   if (image_view->description != (char *) NULL)
    155     image_view->description=DestroyString(image_view->description);
    156   image_view->view=DestroyCacheView(image_view->view);
    157   image_view->exception=DestroyExceptionInfo(image_view->exception);
    158   image_view->signature=(~MagickCoreSignature);
    159   image_view=(ImageView *) RelinquishMagickMemory(image_view);
    160   return(image_view);
    161 }
    162 
    163 /*
    165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    166 %                                                                             %
    167 %                                                                             %
    168 %                                                                             %
    169 %   D u p l e x T r a n s f e r I m a g e V i e w I t e r a t o r             %
    170 %                                                                             %
    171 %                                                                             %
    172 %                                                                             %
    173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    174 %
    175 %  DuplexTransferImageViewIterator() iterates over three image views in
    176 %  parallel and calls your transfer method for each scanline of the view.  The
    177 %  source and duplex pixel extent is not confined to the image canvas-- that is
    178 %  you can include negative offsets or widths or heights that exceed the image
    179 %  dimension.  However, the destination image view is confined to the image
    180 %  canvas-- that is no negative offsets or widths or heights that exceed the
    181 %  image dimension are permitted.
    182 %
    183 %  The callback signature is:
    184 %
    185 %      MagickBooleanType DuplexTransferImageViewMethod(const ImageView *source,
    186 %        const ImageView *duplex,ImageView *destination,const ssize_t y,
    187 %        const int thread_id,void *context)
    188 %
    189 %  Use this pragma if the view is not single threaded:
    190 %
    191 %    #pragma omp critical
    192 %
    193 %  to define a section of code in your callback transfer method that must be
    194 %  executed by a single thread at a time.
    195 %
    196 %  The format of the DuplexTransferImageViewIterator method is:
    197 %
    198 %      MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
    199 %        ImageView *duplex,ImageView *destination,
    200 %        DuplexTransferImageViewMethod transfer,void *context)
    201 %
    202 %  A description of each parameter follows:
    203 %
    204 %    o source: the source image view.
    205 %
    206 %    o duplex: the duplex image view.
    207 %
    208 %    o destination: the destination image view.
    209 %
    210 %    o transfer: the transfer callback method.
    211 %
    212 %    o context: the user defined context.
    213 %
    214 */
    215 MagickExport MagickBooleanType DuplexTransferImageViewIterator(
    216   ImageView *source,ImageView *duplex,ImageView *destination,
    217   DuplexTransferImageViewMethod transfer,void *context)
    218 {
    219   Image
    220     *destination_image,
    221     *source_image;
    222 
    223   MagickBooleanType
    224     status;
    225 
    226   MagickOffsetType
    227     progress;
    228 
    229 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    230   size_t
    231     height;
    232 #endif
    233 
    234   ssize_t
    235     y;
    236 
    237   assert(source != (ImageView *) NULL);
    238   assert(source->signature == MagickCoreSignature);
    239   if (transfer == (DuplexTransferImageViewMethod) NULL)
    240     return(MagickFalse);
    241   source_image=source->image;
    242   destination_image=destination->image;
    243   status=SetImageStorageClass(destination_image,DirectClass,
    244     destination->exception);
    245   if (status == MagickFalse)
    246     return(MagickFalse);
    247   status=MagickTrue;
    248   progress=0;
    249 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    250   height=source->extent.height-source->extent.y;
    251   #pragma omp parallel for schedule(static,4) shared(progress,status) \
    252     magick_threads(source_image,destination_image,height,1)
    253 #endif
    254   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
    255   {
    256     const int
    257       id = GetOpenMPThreadId();
    258 
    259     MagickBooleanType
    260       sync;
    261 
    262     register const Quantum
    263       *magick_restrict duplex_pixels,
    264       *magick_restrict pixels;
    265 
    266     register Quantum
    267       *magick_restrict destination_pixels;
    268 
    269     if (status == MagickFalse)
    270       continue;
    271     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
    272       source->extent.width,1,source->exception);
    273     if (pixels == (const Quantum *) NULL)
    274       {
    275         status=MagickFalse;
    276         continue;
    277       }
    278     duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
    279       duplex->extent.width,1,duplex->exception);
    280     if (duplex_pixels == (const Quantum *) NULL)
    281       {
    282         status=MagickFalse;
    283         continue;
    284       }
    285     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
    286       destination->extent.x,y,destination->extent.width,1,
    287       destination->exception);
    288     if (destination_pixels == (Quantum *) NULL)
    289       {
    290         status=MagickFalse;
    291         continue;
    292       }
    293     if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
    294       status=MagickFalse;
    295     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
    296     if (sync == MagickFalse)
    297       status=MagickFalse;
    298     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
    299       {
    300         MagickBooleanType
    301           proceed;
    302 
    303 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    304         #pragma omp critical (MagickCore_DuplexTransferImageViewIterator)
    305 #endif
    306         proceed=SetImageProgress(source_image,source->description,progress++,
    307           source->extent.height);
    308         if (proceed == MagickFalse)
    309           status=MagickFalse;
    310       }
    311   }
    312   return(status);
    313 }
    314 
    315 /*
    317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    318 %                                                                             %
    319 %                                                                             %
    320 %                                                                             %
    321 %   G e t I m a g e V i e w A u t h e n t i c M e t a c o n t e n t           %
    322 %                                                                             %
    323 %                                                                             %
    324 %                                                                             %
    325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    326 %
    327 %  GetImageViewAuthenticMetacontent() returns the image view authentic
    328 %  meta-content.
    329 %
    330 %  The format of the GetImageViewAuthenticPixels method is:
    331 %
    332 %      void *GetImageViewAuthenticMetacontent(
    333 %        const ImageView *image_view)
    334 %
    335 %  A description of each parameter follows:
    336 %
    337 %    o image_view: the image view.
    338 %
    339 */
    340 MagickExport void *GetImageViewAuthenticMetacontent(
    341   const ImageView *image_view)
    342 {
    343   assert(image_view != (ImageView *) NULL);
    344   assert(image_view->signature == MagickCoreSignature);
    345   return(GetCacheViewAuthenticMetacontent(image_view->view));
    346 }
    347 
    348 /*
    350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    351 %                                                                             %
    352 %                                                                             %
    353 %                                                                             %
    354 %   G e t I m a g e V i e w A u t h e n t i c P i x e l s                     %
    355 %                                                                             %
    356 %                                                                             %
    357 %                                                                             %
    358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    359 %
    360 %  GetImageViewAuthenticPixels() returns the image view authentic pixels.
    361 %
    362 %  The format of the GetImageViewAuthenticPixels method is:
    363 %
    364 %      Quantum *GetImageViewAuthenticPixels(const ImageView *image_view)
    365 %
    366 %  A description of each parameter follows:
    367 %
    368 %    o image_view: the image view.
    369 %
    370 */
    371 MagickExport Quantum *GetImageViewAuthenticPixels(
    372   const ImageView *image_view)
    373 {
    374   assert(image_view != (ImageView *) NULL);
    375   assert(image_view->signature == MagickCoreSignature);
    376   return(GetCacheViewAuthenticPixelQueue(image_view->view));
    377 }
    378 
    379 /*
    381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    382 %                                                                             %
    383 %                                                                             %
    384 %                                                                             %
    385 %   G e t I m a g e V i e w E x c e p t i o n                                 %
    386 %                                                                             %
    387 %                                                                             %
    388 %                                                                             %
    389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    390 %
    391 %  GetImageViewException() returns the severity, reason, and description of any
    392 %  error that occurs when utilizing a image view.
    393 %
    394 %  The format of the GetImageViewException method is:
    395 %
    396 %      char *GetImageViewException(const PixelImage *image_view,
    397 %        ExceptionType *severity)
    398 %
    399 %  A description of each parameter follows:
    400 %
    401 %    o image_view: the pixel image_view.
    402 %
    403 %    o severity: the severity of the error is returned here.
    404 %
    405 */
    406 MagickExport char *GetImageViewException(const ImageView *image_view,
    407   ExceptionType *severity)
    408 {
    409   char
    410     *description;
    411 
    412   assert(image_view != (const ImageView *) NULL);
    413   assert(image_view->signature == MagickCoreSignature);
    414   assert(severity != (ExceptionType *) NULL);
    415   *severity=image_view->exception->severity;
    416   description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
    417     sizeof(*description));
    418   if (description == (char *) NULL)
    419     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    420   *description='\0';
    421   if (image_view->exception->reason != (char *) NULL)
    422     (void) CopyMagickString(description,GetLocaleExceptionMessage(
    423       image_view->exception->severity,image_view->exception->reason),
    424         MagickPathExtent);
    425   if (image_view->exception->description != (char *) NULL)
    426     {
    427       (void) ConcatenateMagickString(description," (",MagickPathExtent);
    428       (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
    429         image_view->exception->severity,image_view->exception->description),
    430         MagickPathExtent);
    431       (void) ConcatenateMagickString(description,")",MagickPathExtent);
    432     }
    433   return(description);
    434 }
    435 
    436 /*
    438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    439 %                                                                             %
    440 %                                                                             %
    441 %                                                                             %
    442 %   G e t I m a g e V i e w E x t e n t                                       %
    443 %                                                                             %
    444 %                                                                             %
    445 %                                                                             %
    446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    447 %
    448 %  GetImageViewExtent() returns the image view extent.
    449 %
    450 %  The format of the GetImageViewExtent method is:
    451 %
    452 %      RectangleInfo GetImageViewExtent(const ImageView *image_view)
    453 %
    454 %  A description of each parameter follows:
    455 %
    456 %    o image_view: the image view.
    457 %
    458 */
    459 MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
    460 {
    461   assert(image_view != (ImageView *) NULL);
    462   assert(image_view->signature == MagickCoreSignature);
    463   return(image_view->extent);
    464 }
    465 
    466 /*
    468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    469 %                                                                             %
    470 %                                                                             %
    471 %                                                                             %
    472 %   G e t I m a g e V i e w I m a g e                                         %
    473 %                                                                             %
    474 %                                                                             %
    475 %                                                                             %
    476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    477 %
    478 %  GetImageViewImage() returns the image associated with the image view.
    479 %
    480 %  The format of the GetImageViewImage method is:
    481 %
    482 %      MagickCore *GetImageViewImage(const ImageView *image_view)
    483 %
    484 %  A description of each parameter follows:
    485 %
    486 %    o image_view: the image view.
    487 %
    488 */
    489 MagickExport Image *GetImageViewImage(const ImageView *image_view)
    490 {
    491   assert(image_view != (ImageView *) NULL);
    492   assert(image_view->signature == MagickCoreSignature);
    493   return(image_view->image);
    494 }
    495 
    496 /*
    498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    499 %                                                                             %
    500 %                                                                             %
    501 %                                                                             %
    502 %   G e t I m a g e V i e w I t e r a t o r                                   %
    503 %                                                                             %
    504 %                                                                             %
    505 %                                                                             %
    506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    507 %
    508 %  GetImageViewIterator() iterates over the image view in parallel and calls
    509 %  your get method for each scanline of the view.  The pixel extent is
    510 %  not confined to the image canvas-- that is you can include negative offsets
    511 %  or widths or heights that exceed the image dimension.  Any updates to
    512 %  the pixels in your callback are ignored.
    513 %
    514 %  The callback signature is:
    515 %
    516 %      MagickBooleanType GetImageViewMethod(const ImageView *source,
    517 %        const ssize_t y,const int thread_id,void *context)
    518 %
    519 %  Use this pragma if the view is not single threaded:
    520 %
    521 %    #pragma omp critical
    522 %
    523 %  to define a section of code in your callback get method that must be
    524 %  executed by a single thread at a time.
    525 %
    526 %  The format of the GetImageViewIterator method is:
    527 %
    528 %      MagickBooleanType GetImageViewIterator(ImageView *source,
    529 %        GetImageViewMethod get,void *context)
    530 %
    531 %  A description of each parameter follows:
    532 %
    533 %    o source: the source image view.
    534 %
    535 %    o get: the get callback method.
    536 %
    537 %    o context: the user defined context.
    538 %
    539 */
    540 MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
    541   GetImageViewMethod get,void *context)
    542 {
    543   Image
    544     *source_image;
    545 
    546   MagickBooleanType
    547     status;
    548 
    549   MagickOffsetType
    550     progress;
    551 
    552 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    553   size_t
    554     height;
    555 #endif
    556 
    557   ssize_t
    558     y;
    559 
    560   assert(source != (ImageView *) NULL);
    561   assert(source->signature == MagickCoreSignature);
    562   if (get == (GetImageViewMethod) NULL)
    563     return(MagickFalse);
    564   source_image=source->image;
    565   status=MagickTrue;
    566   progress=0;
    567 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    568   height=source->extent.height-source->extent.y;
    569   #pragma omp parallel for schedule(static,4) shared(progress,status) \
    570     magick_threads(source_image,source_image,height,1)
    571 #endif
    572   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
    573   {
    574     const int
    575       id = GetOpenMPThreadId();
    576 
    577     register const Quantum
    578       *pixels;
    579 
    580     if (status == MagickFalse)
    581       continue;
    582     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
    583       source->extent.width,1,source->exception);
    584     if (pixels == (const Quantum *) NULL)
    585       {
    586         status=MagickFalse;
    587         continue;
    588       }
    589     if (get(source,y,id,context) == MagickFalse)
    590       status=MagickFalse;
    591     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
    592       {
    593         MagickBooleanType
    594           proceed;
    595 
    596 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    597         #pragma omp critical (MagickCore_GetImageViewIterator)
    598 #endif
    599         proceed=SetImageProgress(source_image,source->description,progress++,
    600           source->extent.height);
    601         if (proceed == MagickFalse)
    602           status=MagickFalse;
    603       }
    604   }
    605   return(status);
    606 }
    607 
    608 /*
    610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    611 %                                                                             %
    612 %                                                                             %
    613 %                                                                             %
    614 %   G e t I m a g e V i e w V i r t u a l M e t a c o n t e n t     %
    615 %                                                                             %
    616 %                                                                             %
    617 %                                                                             %
    618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    619 %
    620 %  GetImageViewVirtualMetacontent() returns the image view virtual
    621 %  meta-content.
    622 %
    623 %  The format of the GetImageViewVirtualMetacontent method is:
    624 %
    625 %      const void *GetImageViewVirtualMetacontent(
    626 %        const ImageView *image_view)
    627 %
    628 %  A description of each parameter follows:
    629 %
    630 %    o image_view: the image view.
    631 %
    632 */
    633 MagickExport const void *GetImageViewVirtualMetacontent(
    634   const ImageView *image_view)
    635 {
    636   assert(image_view != (ImageView *) NULL);
    637   assert(image_view->signature == MagickCoreSignature);
    638   return(GetCacheViewVirtualMetacontent(image_view->view));
    639 }
    640 
    641 /*
    643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    644 %                                                                             %
    645 %                                                                             %
    646 %                                                                             %
    647 %   G e t I m a g e V i e w V i r t u a l P i x e l s                         %
    648 %                                                                             %
    649 %                                                                             %
    650 %                                                                             %
    651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    652 %
    653 %  GetImageViewVirtualPixels() returns the image view virtual pixels.
    654 %
    655 %  The format of the GetImageViewVirtualPixels method is:
    656 %
    657 %      const Quantum *GetImageViewVirtualPixels(const ImageView *image_view)
    658 %
    659 %  A description of each parameter follows:
    660 %
    661 %    o image_view: the image view.
    662 %
    663 */
    664 MagickExport const Quantum *GetImageViewVirtualPixels(
    665   const ImageView *image_view)
    666 {
    667   assert(image_view != (ImageView *) NULL);
    668   assert(image_view->signature == MagickCoreSignature);
    669   return(GetCacheViewVirtualPixelQueue(image_view->view));
    670 }
    671 
    672 /*
    674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    675 %                                                                             %
    676 %                                                                             %
    677 %                                                                             %
    678 %   I s I m a g e V i e w                                                     %
    679 %                                                                             %
    680 %                                                                             %
    681 %                                                                             %
    682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    683 %
    684 %  IsImageView() returns MagickTrue if the the parameter is verified as a image
    685 %  view object.
    686 %
    687 %  The format of the IsImageView method is:
    688 %
    689 %      MagickBooleanType IsImageView(const ImageView *image_view)
    690 %
    691 %  A description of each parameter follows:
    692 %
    693 %    o image_view: the image view.
    694 %
    695 */
    696 MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
    697 {
    698   if (image_view == (const ImageView *) NULL)
    699     return(MagickFalse);
    700   if (image_view->signature != MagickCoreSignature)
    701     return(MagickFalse);
    702   return(MagickTrue);
    703 }
    704 
    705 /*
    707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    708 %                                                                             %
    709 %                                                                             %
    710 %                                                                             %
    711 %   N e w I m a g e V i e w                                                   %
    712 %                                                                             %
    713 %                                                                             %
    714 %                                                                             %
    715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    716 %
    717 %  NewImageView() returns a image view required for all other methods in the
    718 %  Image View API.
    719 %
    720 %  The format of the NewImageView method is:
    721 %
    722 %      ImageView *NewImageView(MagickCore *wand,ExceptionInfo *exception)
    723 %
    724 %  A description of each parameter follows:
    725 %
    726 %    o image: the image.
    727 %
    728 %    o exception: return any errors or warnings in this structure.
    729 %
    730 */
    731 MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception)
    732 {
    733   ImageView
    734     *image_view;
    735 
    736   assert(image != (Image *) NULL);
    737   assert(image->signature == MagickCoreSignature);
    738   image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
    739   if (image_view == (ImageView *) NULL)
    740     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    741   (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
    742   image_view->description=ConstantString("ImageView");
    743   image_view->image=image;
    744   image_view->view=AcquireVirtualCacheView(image_view->image,exception);
    745   image_view->extent.width=image->columns;
    746   image_view->extent.height=image->rows;
    747   image_view->extent.x=0;
    748   image_view->extent.y=0;
    749   image_view->exception=AcquireExceptionInfo();
    750   image_view->debug=IsEventLogging();
    751   image_view->signature=MagickCoreSignature;
    752   return(image_view);
    753 }
    754 
    755 /*
    757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    758 %                                                                             %
    759 %                                                                             %
    760 %                                                                             %
    761 %   N e w I m a g e V i e w R e g i o n                                       %
    762 %                                                                             %
    763 %                                                                             %
    764 %                                                                             %
    765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    766 %
    767 %  NewImageViewRegion() returns a image view required for all other methods
    768 %  in the Image View API.
    769 %
    770 %  The format of the NewImageViewRegion method is:
    771 %
    772 %      ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
    773 %        const ssize_t y,const size_t width,const size_t height,
    774 %        ExceptionInfo *exception)
    775 %
    776 %  A description of each parameter follows:
    777 %
    778 %    o wand: the magick wand.
    779 %
    780 %    o x,y,columns,rows:  These values define the perimeter of a extent of
    781 %      pixel_wands view.
    782 %
    783 %    o exception: return any errors or warnings in this structure.
    784 %
    785 */
    786 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
    787   const ssize_t y,const size_t width,const size_t height,
    788   ExceptionInfo *exception)
    789 {
    790   ImageView
    791     *image_view;
    792 
    793   assert(image != (Image *) NULL);
    794   assert(image->signature == MagickCoreSignature);
    795   image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
    796   if (image_view == (ImageView *) NULL)
    797     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    798   (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
    799   image_view->description=ConstantString("ImageView");
    800   image_view->view=AcquireVirtualCacheView(image_view->image,exception);
    801   image_view->image=image;
    802   image_view->extent.width=width;
    803   image_view->extent.height=height;
    804   image_view->extent.x=x;
    805   image_view->extent.y=y;
    806   image_view->exception=AcquireExceptionInfo();
    807   image_view->debug=IsEventLogging();
    808   image_view->signature=MagickCoreSignature;
    809   return(image_view);
    810 }
    811 
    812 /*
    814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    815 %                                                                             %
    816 %                                                                             %
    817 %                                                                             %
    818 %   S e t I m a g e V i e w D e s c r i p t i o n                             %
    819 %                                                                             %
    820 %                                                                             %
    821 %                                                                             %
    822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    823 %
    824 %  SetImageViewDescription() associates a description with an image view.
    825 %
    826 %  The format of the SetImageViewDescription method is:
    827 %
    828 %      void SetImageViewDescription(ImageView *image_view,
    829 %        const char *description)
    830 %
    831 %  A description of each parameter follows:
    832 %
    833 %    o image_view: the image view.
    834 %
    835 %    o description: the image view description.
    836 %
    837 */
    838 MagickExport void SetImageViewDescription(ImageView *image_view,
    839   const char *description)
    840 {
    841   assert(image_view != (ImageView *) NULL);
    842   assert(image_view->signature == MagickCoreSignature);
    843   image_view->description=ConstantString(description);
    844 }
    845 
    846 /*
    848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    849 %                                                                             %
    850 %                                                                             %
    851 %                                                                             %
    852 %   S e t I m a g e V i e w I t e r a t o r                                   %
    853 %                                                                             %
    854 %                                                                             %
    855 %                                                                             %
    856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    857 %
    858 %  SetImageViewIterator() iterates over the image view in parallel and calls
    859 %  your set method for each scanline of the view.  The pixel extent is
    860 %  confined to the image canvas-- that is no negative offsets or widths or
    861 %  heights that exceed the image dimension.  The pixels are initiallly
    862 %  undefined and any settings you make in the callback method are automagically
    863 %  synced back to your image.
    864 %
    865 %  The callback signature is:
    866 %
    867 %      MagickBooleanType SetImageViewMethod(ImageView *destination,
    868 %        const ssize_t y,const int thread_id,void *context)
    869 %
    870 %  Use this pragma if the view is not single threaded:
    871 %
    872 %    #pragma omp critical
    873 %
    874 %  to define a section of code in your callback set method that must be
    875 %  executed by a single thread at a time.
    876 %
    877 %  The format of the SetImageViewIterator method is:
    878 %
    879 %      MagickBooleanType SetImageViewIterator(ImageView *destination,
    880 %        SetImageViewMethod set,void *context)
    881 %
    882 %  A description of each parameter follows:
    883 %
    884 %    o destination: the image view.
    885 %
    886 %    o set: the set callback method.
    887 %
    888 %    o context: the user defined context.
    889 %
    890 */
    891 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
    892   SetImageViewMethod set,void *context)
    893 {
    894   Image
    895     *destination_image;
    896 
    897   MagickBooleanType
    898     status;
    899 
    900   MagickOffsetType
    901     progress;
    902 
    903 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    904   size_t
    905     height;
    906 #endif
    907 
    908   ssize_t
    909     y;
    910 
    911   assert(destination != (ImageView *) NULL);
    912   assert(destination->signature == MagickCoreSignature);
    913   if (set == (SetImageViewMethod) NULL)
    914     return(MagickFalse);
    915   destination_image=destination->image;
    916   status=SetImageStorageClass(destination_image,DirectClass,
    917     destination->exception);
    918   if (status == MagickFalse)
    919     return(MagickFalse);
    920   status=MagickTrue;
    921   progress=0;
    922 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    923   height=destination->extent.height-destination->extent.y;
    924   #pragma omp parallel for schedule(static,4) shared(progress,status) \
    925     magick_threads(destination_image,destination_image,height,1)
    926 #endif
    927   for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
    928   {
    929     const int
    930       id = GetOpenMPThreadId();
    931 
    932     MagickBooleanType
    933       sync;
    934 
    935     register Quantum
    936       *magick_restrict pixels;
    937 
    938     if (status == MagickFalse)
    939       continue;
    940     pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
    941       y,destination->extent.width,1,destination->exception);
    942     if (pixels == (Quantum *) NULL)
    943       {
    944         status=MagickFalse;
    945         continue;
    946       }
    947     if (set(destination,y,id,context) == MagickFalse)
    948       status=MagickFalse;
    949     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
    950     if (sync == MagickFalse)
    951       status=MagickFalse;
    952     if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
    953       {
    954         MagickBooleanType
    955           proceed;
    956 
    957 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    958         #pragma omp critical (MagickCore_SetImageViewIterator)
    959 #endif
    960         proceed=SetImageProgress(destination_image,destination->description,
    961           progress++,destination->extent.height);
    962         if (proceed == MagickFalse)
    963           status=MagickFalse;
    964       }
    965   }
    966   return(status);
    967 }
    968 
    969 /*
    971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    972 %                                                                             %
    973 %                                                                             %
    974 %                                                                             %
    975 %   T r a n s f e r I m a g e V i e w I t e r a t o r                         %
    976 %                                                                             %
    977 %                                                                             %
    978 %                                                                             %
    979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    980 %
    981 %  TransferImageViewIterator() iterates over two image views in parallel and
    982 %  calls your transfer method for each scanline of the view.  The source pixel
    983 %  extent is not confined to the image canvas-- that is you can include
    984 %  negative offsets or widths or heights that exceed the image dimension.
    985 %  However, the destination image view is confined to the image canvas-- that
    986 %  is no negative offsets or widths or heights that exceed the image dimension
    987 %  are permitted.
    988 %
    989 %  The callback signature is:
    990 %
    991 %      MagickBooleanType TransferImageViewMethod(const ImageView *source,
    992 %        ImageView *destination,const ssize_t y,const int thread_id,
    993 %        void *context)
    994 %
    995 %  Use this pragma if the view is not single threaded:
    996 %
    997 %    #pragma omp critical
    998 %
    999 %  to define a section of code in your callback transfer method that must be
   1000 %  executed by a single thread at a time.
   1001 %
   1002 %  The format of the TransferImageViewIterator method is:
   1003 %
   1004 %      MagickBooleanType TransferImageViewIterator(ImageView *source,
   1005 %        ImageView *destination,TransferImageViewMethod transfer,void *context)
   1006 %
   1007 %  A description of each parameter follows:
   1008 %
   1009 %    o source: the source image view.
   1010 %
   1011 %    o destination: the destination image view.
   1012 %
   1013 %    o transfer: the transfer callback method.
   1014 %
   1015 %    o context: the user defined context.
   1016 %
   1017 */
   1018 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
   1019   ImageView *destination,TransferImageViewMethod transfer,void *context)
   1020 {
   1021   Image
   1022     *destination_image,
   1023     *source_image;
   1024 
   1025   MagickBooleanType
   1026     status;
   1027 
   1028   MagickOffsetType
   1029     progress;
   1030 
   1031 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1032   size_t
   1033     height;
   1034 #endif
   1035 
   1036   ssize_t
   1037     y;
   1038 
   1039   assert(source != (ImageView *) NULL);
   1040   assert(source->signature == MagickCoreSignature);
   1041   if (transfer == (TransferImageViewMethod) NULL)
   1042     return(MagickFalse);
   1043   source_image=source->image;
   1044   destination_image=destination->image;
   1045   status=SetImageStorageClass(destination_image,DirectClass,
   1046     destination->exception);
   1047   if (status == MagickFalse)
   1048     return(MagickFalse);
   1049   status=MagickTrue;
   1050   progress=0;
   1051 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1052   height=source->extent.height-source->extent.y;
   1053   #pragma omp parallel for schedule(static,4) shared(progress,status) \
   1054     magick_threads(source_image,destination_image,height,1)
   1055 #endif
   1056   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
   1057   {
   1058     const int
   1059       id = GetOpenMPThreadId();
   1060 
   1061     MagickBooleanType
   1062       sync;
   1063 
   1064     register const Quantum
   1065       *magick_restrict pixels;
   1066 
   1067     register Quantum
   1068       *magick_restrict destination_pixels;
   1069 
   1070     if (status == MagickFalse)
   1071       continue;
   1072     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
   1073       source->extent.width,1,source->exception);
   1074     if (pixels == (const Quantum *) NULL)
   1075       {
   1076         status=MagickFalse;
   1077         continue;
   1078       }
   1079     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
   1080       destination->extent.x,y,destination->extent.width,1,
   1081       destination->exception);
   1082     if (destination_pixels == (Quantum *) NULL)
   1083       {
   1084         status=MagickFalse;
   1085         continue;
   1086       }
   1087     if (transfer(source,destination,y,id,context) == MagickFalse)
   1088       status=MagickFalse;
   1089     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
   1090     if (sync == MagickFalse)
   1091       status=MagickFalse;
   1092     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
   1093       {
   1094         MagickBooleanType
   1095           proceed;
   1096 
   1097 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1098         #pragma omp critical (MagickCore_TransferImageViewIterator)
   1099 #endif
   1100         proceed=SetImageProgress(source_image,source->description,progress++,
   1101           source->extent.height);
   1102         if (proceed == MagickFalse)
   1103           status=MagickFalse;
   1104       }
   1105   }
   1106   return(status);
   1107 }
   1108 
   1109 /*
   1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1112 %                                                                             %
   1113 %                                                                             %
   1114 %                                                                             %
   1115 %   U p d a t e I m a g e V i e w I t e r a t o r                             %
   1116 %                                                                             %
   1117 %                                                                             %
   1118 %                                                                             %
   1119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1120 %
   1121 %  UpdateImageViewIterator() iterates over the image view in parallel and calls
   1122 %  your update method for each scanline of the view.  The pixel extent is
   1123 %  confined to the image canvas-- that is no negative offsets or widths or
   1124 %  heights that exceed the image dimension are permitted.  Updates to pixels
   1125 %  in your callback are automagically synced back to the image.
   1126 %
   1127 %  The callback signature is:
   1128 %
   1129 %      MagickBooleanType UpdateImageViewMethod(ImageView *source,
   1130 %        const ssize_t y,const int thread_id,void *context)
   1131 %
   1132 %  Use this pragma if the view is not single threaded:
   1133 %
   1134 %    #pragma omp critical
   1135 %
   1136 %  to define a section of code in your callback update method that must be
   1137 %  executed by a single thread at a time.
   1138 %
   1139 %  The format of the UpdateImageViewIterator method is:
   1140 %
   1141 %      MagickBooleanType UpdateImageViewIterator(ImageView *source,
   1142 %        UpdateImageViewMethod update,void *context)
   1143 %
   1144 %  A description of each parameter follows:
   1145 %
   1146 %    o source: the source image view.
   1147 %
   1148 %    o update: the update callback method.
   1149 %
   1150 %    o context: the user defined context.
   1151 %
   1152 */
   1153 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
   1154   UpdateImageViewMethod update,void *context)
   1155 {
   1156   Image
   1157     *source_image;
   1158 
   1159   MagickBooleanType
   1160     status;
   1161 
   1162   MagickOffsetType
   1163     progress;
   1164 
   1165 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1166   size_t
   1167     height;
   1168 #endif
   1169 
   1170   ssize_t
   1171     y;
   1172 
   1173   assert(source != (ImageView *) NULL);
   1174   assert(source->signature == MagickCoreSignature);
   1175   if (update == (UpdateImageViewMethod) NULL)
   1176     return(MagickFalse);
   1177   source_image=source->image;
   1178   status=SetImageStorageClass(source_image,DirectClass,source->exception);
   1179   if (status == MagickFalse)
   1180     return(MagickFalse);
   1181   status=MagickTrue;
   1182   progress=0;
   1183 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1184   height=source->extent.height-source->extent.y;
   1185   #pragma omp parallel for schedule(static,4) shared(progress,status) \
   1186     magick_threads(source_image,source_image,height,1)
   1187 #endif
   1188   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
   1189   {
   1190     const int
   1191       id = GetOpenMPThreadId();
   1192 
   1193     register Quantum
   1194       *magick_restrict pixels;
   1195 
   1196     if (status == MagickFalse)
   1197       continue;
   1198     pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
   1199       source->extent.width,1,source->exception);
   1200     if (pixels == (Quantum *) NULL)
   1201       {
   1202         status=MagickFalse;
   1203         continue;
   1204       }
   1205     if (update(source,y,id,context) == MagickFalse)
   1206       status=MagickFalse;
   1207     status=SyncCacheViewAuthenticPixels(source->view,source->exception);
   1208     if (status == MagickFalse)
   1209       status=MagickFalse;
   1210     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
   1211       {
   1212         MagickBooleanType
   1213           proceed;
   1214 
   1215 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   1216         #pragma omp critical (MagickCore_UpdateImageViewIterator)
   1217 #endif
   1218         proceed=SetImageProgress(source_image,source->description,progress++,
   1219           source->extent.height);
   1220         if (proceed == MagickFalse)
   1221           status=MagickFalse;
   1222       }
   1223   }
   1224   return(status);
   1225 }
   1226