48#include "MagickWand/studio.h" 
   49#include "MagickWand/MagickWand.h" 
   50#include "MagickWand/magick-wand-private.h" 
   51#include "MagickWand/wand.h" 
   52#include "MagickCore/monitor-private.h" 
   53#include "MagickCore/thread-private.h" 
   57#define WandViewId  "WandView" 
   68    name[MagickPathExtent],
 
 
  118WandExport WandView *CloneWandView(
const WandView *wand_view)
 
  126  assert(wand_view != (WandView *) NULL);
 
  127  assert(wand_view->signature == MagickWandSignature);
 
  128  if (wand_view->debug != MagickFalse)
 
  129    (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",wand_view->name);
 
  130  clone_view=(WandView *) AcquireCriticalMemory(
sizeof(*clone_view));
 
  131  (void) memset(clone_view,0,
sizeof(*clone_view));
 
  132  clone_view->id=AcquireWandId();
 
  133  (void) FormatLocaleString(clone_view->name,MagickPathExtent,
"%s-%.20g",
 
  134    WandViewId,(
double) clone_view->id);
 
  135  clone_view->description=ConstantString(wand_view->description);
 
  136  clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
 
  137    wand_view->exception);
 
  138  clone_view->view=CloneCacheView(wand_view->view);
 
  139  clone_view->extent=wand_view->extent;
 
  140  clone_view->exception=AcquireExceptionInfo();
 
  141  InheritException(clone_view->exception,wand_view->exception);
 
  142  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
 
  143    clone_view->pixel_wands[i]=ClonePixelWands((
const PixelWand **)
 
  144      wand_view->pixel_wands[i],wand_view->extent.width);
 
  145  clone_view->debug=wand_view->debug;
 
  146  if (clone_view->debug != MagickFalse)
 
  147    (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",clone_view->name);
 
  148  clone_view->signature=MagickWandSignature;
 
  175static PixelWand ***DestroyPixelsTLS(PixelWand ***pixel_wands,
 
  176  const size_t number_wands)
 
  181  assert(pixel_wands != (PixelWand ***) NULL);
 
  182  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
 
  183    if (pixel_wands[i] != (PixelWand **) NULL)
 
  184      pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
 
  185  pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
 
  189WandExport WandView *DestroyWandView(WandView *wand_view)
 
  191  assert(wand_view != (WandView *) NULL);
 
  192  assert(wand_view->signature == MagickWandSignature);
 
  193  wand_view->pixel_wands=DestroyPixelsTLS(wand_view->pixel_wands,
 
  194    wand_view->extent.width);
 
  195  wand_view->view=DestroyCacheView(wand_view->view);
 
  196  wand_view->exception=DestroyExceptionInfo(wand_view->exception);
 
  197  wand_view->signature=(~MagickWandSignature);
 
  198  RelinquishWandId(wand_view->id);
 
  199  wand_view=(WandView *) RelinquishMagickMemory(wand_view);
 
  254WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
 
  255  WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
 
  268#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  276  assert(source != (WandView *) NULL);
 
  277  assert(source->signature == MagickWandSignature);
 
  278  if (transfer == (DuplexTransferWandViewMethod) NULL)
 
  280  source_image=source->wand->images;
 
  281  destination_image=destination->wand->images;
 
  282  status=SetImageStorageClass(destination_image,DirectClass,
 
  283    destination->exception);
 
  284  if (status == MagickFalse)
 
  288#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  289  height=(size_t) ((ssize_t) source->extent.height-source->extent.y);
 
  290  #pragma omp parallel for schedule(static) shared(progress,status) \ 
  291    magick_number_threads(source_image,destination_image,height,1) 
  293  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
 
  296      id = GetOpenMPThreadId();
 
  302      *magick_restrict duplex_pixels,
 
  303      *magick_restrict pixels;
 
  309      *magick_restrict destination_pixels;
 
  311    if (status == MagickFalse)
 
  313    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
 
  314      source->extent.width,1,source->exception);
 
  315    if (pixels == (
const Quantum *) NULL)
 
  320    for (x=0; x < (ssize_t) source->extent.width; x++)
 
  322      PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
 
  323      pixels+=(ptrdiff_t) GetPixelChannels(source->image);
 
  325    duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
 
  326      duplex->extent.width,1,duplex->exception);
 
  327    if (duplex_pixels == (
const Quantum *) NULL)
 
  332    for (x=0; x < (ssize_t) duplex->extent.width; x++)
 
  334      PixelSetQuantumPixel(duplex->image,duplex_pixels,
 
  335        duplex->pixel_wands[
id][x]);
 
  336      duplex_pixels+=(ptrdiff_t) GetPixelChannels(duplex->image);
 
  338    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
 
  339      destination->extent.x,y,destination->extent.width,1,
 
  340      destination->exception);
 
  341    if (destination_pixels == (Quantum *) NULL)
 
  346    for (x=0; x < (ssize_t) destination->extent.width; x++)
 
  348      PixelSetQuantumPixel(destination->image,destination_pixels,
 
  349        destination->pixel_wands[
id][x]);
 
  350      destination_pixels+=(ptrdiff_t) GetPixelChannels(destination->image);
 
  352    if (transfer(source,duplex,destination,y,
id,context) == MagickFalse)
 
  354    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
 
  355      destination->extent.x,y,destination->extent.width,1,
 
  356      destination->exception);
 
  357    for (x=0; x < (ssize_t) destination->extent.width; x++)
 
  359      PixelGetQuantumPixel(destination->image,destination->pixel_wands[
id][x],
 
  361      destination_pixels+=(ptrdiff_t) GetPixelChannels(destination->image);
 
  363    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
 
  364    if (sync == MagickFalse)
 
  366    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
 
  371#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  375        proceed=SetImageProgress(source_image,source->description,progress,
 
  376          source->extent.height);
 
  377        if (proceed == MagickFalse)
 
  410WandExport 
char *GetWandViewException(
const WandView *wand_view,
 
  411  ExceptionType *severity)
 
  416  assert(wand_view != (
const WandView *) NULL);
 
  417  assert(wand_view->signature == MagickWandSignature);
 
  418  if (wand_view->debug != MagickFalse)
 
  419    (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",wand_view->name);
 
  420  assert(severity != (ExceptionType *) NULL);
 
  421  *severity=wand_view->exception->severity;
 
  422  description=(
char *) AcquireQuantumMemory(2UL*MagickPathExtent,
 
  423    sizeof(*description));
 
  424  if (description == (
char *) NULL)
 
  425    ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
 
  428  if (wand_view->exception->reason != (
char *) NULL)
 
  429    (void) CopyMagickString(description,GetLocaleExceptionMessage(
 
  430      wand_view->exception->severity,wand_view->exception->reason),
 
  432  if (wand_view->exception->description != (
char *) NULL)
 
  434      (void) ConcatenateMagickString(description,
" (",MagickPathExtent);
 
  435      (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
 
  436        wand_view->exception->severity,wand_view->exception->description),
 
  438      (void) ConcatenateMagickString(description,
")",MagickPathExtent);
 
  465WandExport RectangleInfo GetWandViewExtent(
const WandView *wand_view)
 
  467  assert(wand_view != (WandView *) NULL);
 
  468  assert(wand_view->signature == MagickWandSignature);
 
  469  return(wand_view->extent);
 
  515WandExport MagickBooleanType GetWandViewIterator(WandView *source,
 
  516  GetWandViewMethod get,
void *context)
 
  527#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  535  assert(source != (WandView *) NULL);
 
  536  assert(source->signature == MagickWandSignature);
 
  537  if (get == (GetWandViewMethod) NULL)
 
  539  source_image=source->wand->images;
 
  542#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  543  height=(size_t) ((ssize_t) source->extent.height-source->extent.y);
 
  544  #pragma omp parallel for schedule(static) shared(progress,status) \ 
  545    magick_number_threads(source_image,source_image,height,1) 
  547  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
 
  550      id = GetOpenMPThreadId();
 
  558    if (status == MagickFalse)
 
  560    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
 
  561      source->extent.width,1,source->exception);
 
  562    if (pixels == (
const Quantum *) NULL)
 
  567    for (x=0; x < (ssize_t) source->extent.width; x++)
 
  569      PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
 
  570      pixels+=(ptrdiff_t) GetPixelChannels(source->image);
 
  572    if (get(source,y,
id,context) == MagickFalse)
 
  574    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
 
  579#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  583        proceed=SetImageProgress(source_image,source->description,progress,
 
  584          source->extent.height);
 
  585        if (proceed == MagickFalse)
 
  614WandExport PixelWand **GetWandViewPixels(
const WandView *wand_view)
 
  617    id = GetOpenMPThreadId();
 
  619  assert(wand_view != (WandView *) NULL);
 
  620  assert(wand_view->signature == MagickWandSignature);
 
  621  return(wand_view->pixel_wands[
id]);
 
  646WandExport MagickWand *GetWandViewWand(
const WandView *wand_view)
 
  648  assert(wand_view != (WandView *) NULL);
 
  649  assert(wand_view->signature == MagickWandSignature);
 
  650  return(wand_view->wand);
 
  676WandExport MagickBooleanType IsWandView(
const WandView *wand_view)
 
  681  if (wand_view == (
const WandView *) NULL)
 
  683  if (wand_view->signature != MagickWandSignature)
 
  685  length=strlen(WandViewId);
 
  686  if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
 
  715static PixelWand ***AcquirePixelsTLS(
const size_t number_wands)
 
  726  number_threads=GetOpenMPMaximumThreads();
 
  727  pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
 
  728    sizeof(*pixel_wands));
 
  729  if (pixel_wands == (PixelWand ***) NULL)
 
  730    return((PixelWand ***) NULL);
 
  731  (void) memset(pixel_wands,0,number_threads*
sizeof(*pixel_wands));
 
  732  for (i=0; i < (ssize_t) number_threads; i++)
 
  734    pixel_wands[i]=NewPixelWands(number_wands);
 
  735    if (pixel_wands[i] == (PixelWand **) NULL)
 
  736      return(DestroyPixelsTLS(pixel_wands,number_wands));
 
  741WandExport WandView *NewWandView(MagickWand *wand)
 
  749  assert(wand != (MagickWand *) NULL);
 
  750  assert(wand->signature == MagickWandSignature);
 
  751  wand_view=(WandView *) AcquireCriticalMemory(
sizeof(*wand_view));
 
  752  (void) memset(wand_view,0,
sizeof(*wand_view));
 
  753  wand_view->id=AcquireWandId();
 
  754  (void) FormatLocaleString(wand_view->name,MagickPathExtent,
"%s-%.20g",
 
  755    WandViewId,(
double) wand_view->id);
 
  756  wand_view->description=ConstantString(
"WandView");
 
  757  wand_view->wand=wand;
 
  758  exception=AcquireExceptionInfo();
 
  759  wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
 
  760  wand_view->image=(Image *) GetCacheViewImage(wand_view->view);
 
  761  wand_view->extent.width=wand_view->image->columns;
 
  762  wand_view->extent.height=wand_view->image->rows;
 
  763  wand_view->pixel_wands=AcquirePixelsTLS(wand_view->extent.width);
 
  764  wand_view->exception=exception;
 
  765  if (wand_view->pixel_wands == (PixelWand ***) NULL)
 
  766    ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
 
  767      GetExceptionMessage(errno));
 
  768  wand_view->debug=IsEventLogging();
 
  769  wand_view->signature=MagickWandSignature;
 
  800WandExport WandView *NewWandViewExtent(MagickWand *wand,
const ssize_t x,
 
  801  const ssize_t y,
const size_t width,
const size_t height)
 
  809  assert(wand != (MagickWand *) NULL);
 
  810  assert(wand->signature == MagickWandSignature);
 
  811  wand_view=(WandView *) AcquireCriticalMemory(
sizeof(*wand_view));
 
  812  (void) memset(wand_view,0,
sizeof(*wand_view));
 
  813  wand_view->id=AcquireWandId();
 
  814  (void) FormatLocaleString(wand_view->name,MagickPathExtent,
"%s-%.20g",
 
  815    WandViewId,(
double) wand_view->id);
 
  816  wand_view->description=ConstantString(
"WandView");
 
  817  exception=AcquireExceptionInfo();
 
  818  wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
 
  819  wand_view->wand=wand;
 
  820  wand_view->extent.width=width;
 
  821  wand_view->extent.height=height;
 
  822  wand_view->extent.x=x;
 
  823  wand_view->extent.y=y;
 
  824  wand_view->exception=exception;
 
  825  wand_view->pixel_wands=AcquirePixelsTLS(wand_view->extent.width);
 
  826  if (wand_view->pixel_wands == (PixelWand ***) NULL)
 
  827    ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
 
  828      GetExceptionMessage(errno));
 
  829  wand_view->debug=IsEventLogging();
 
  830  wand_view->signature=MagickWandSignature;
 
  858MagickExport 
void SetWandViewDescription(WandView *wand_view,
 
  859  const char *description)
 
  861  assert(wand_view != (WandView *) NULL);
 
  862  assert(wand_view->signature == MagickWandSignature);
 
  863  wand_view->description=ConstantString(description);
 
  910WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
 
  911  SetWandViewMethod set,
void *context)
 
  922#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  930  assert(destination != (WandView *) NULL);
 
  931  assert(destination->signature == MagickWandSignature);
 
  932  if (set == (SetWandViewMethod) NULL)
 
  934  destination_image=destination->wand->images;
 
  935  status=SetImageStorageClass(destination_image,DirectClass,
 
  936    destination->exception);
 
  937  if (status == MagickFalse)
 
  941#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  942  height=(size_t) ((ssize_t) destination->extent.height-destination->extent.y);
 
  943  #pragma omp parallel for schedule(static) shared(progress,status) \ 
  944    magick_number_threads(destination_image,destination_image,height,1) 
  946  for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
 
  949      id = GetOpenMPThreadId();
 
  955      *magick_restrict pixels;
 
  960    if (status == MagickFalse)
 
  962    pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
 
  963      y,destination->extent.width,1,destination->exception);
 
  964    if (pixels == (Quantum *) NULL)
 
  969    if (set(destination,y,
id,context) == MagickFalse)
 
  971    for (x=0; x < (ssize_t) destination->extent.width; x++)
 
  973      PixelGetQuantumPixel(destination->image,destination->pixel_wands[
id][x],
 
  975      pixels+=(ptrdiff_t) GetPixelChannels(destination->image);
 
  977    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
 
  978    if (sync == MagickFalse)
 
  980    if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
 
  985#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  989        proceed=SetImageProgress(destination_image,destination->description,
 
  990          progress,destination->extent.height);
 
  991        if (proceed == MagickFalse)
 
 1046WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
 
 1047  WandView *destination,TransferWandViewMethod transfer,
void *context)
 
 1059#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1067  assert(source != (WandView *) NULL);
 
 1068  assert(source->signature == MagickWandSignature);
 
 1069  if (transfer == (TransferWandViewMethod) NULL)
 
 1070    return(MagickFalse);
 
 1071  source_image=source->wand->images;
 
 1072  destination_image=destination->wand->images;
 
 1073  status=SetImageStorageClass(destination_image,DirectClass,
 
 1074    destination->exception);
 
 1075  if (status == MagickFalse)
 
 1076    return(MagickFalse);
 
 1079#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1080  height=(size_t) ((ssize_t) source->extent.height-source->extent.y);
 
 1081  #pragma omp parallel for schedule(static) shared(progress,status) \ 
 1082    magick_number_threads(source_image,destination_image,height,1) 
 1084  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
 
 1087      id = GetOpenMPThreadId();
 
 1090      *magick_restrict pixels;
 
 1096      *magick_restrict destination_pixels;
 
 1101    if (status == MagickFalse)
 
 1103    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
 
 1104      source->extent.width,1,source->exception);
 
 1105    if (pixels == (
const Quantum *) NULL)
 
 1110    for (x=0; x < (ssize_t) source->extent.width; x++)
 
 1112      PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
 
 1113      pixels+=(ptrdiff_t) GetPixelChannels(source->image);
 
 1115    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
 
 1116      destination->extent.x,y,destination->extent.width,1,
 
 1117      destination->exception);
 
 1118    if (destination_pixels == (Quantum *) NULL)
 
 1123    for (x=0; x < (ssize_t) destination->extent.width; x++)
 
 1125      PixelSetQuantumPixel(destination->image,destination_pixels,
 
 1126        destination->pixel_wands[
id][x]);
 
 1127      destination_pixels+=(ptrdiff_t) GetPixelChannels(destination->image);
 
 1129    if (transfer(source,destination,y,
id,context) == MagickFalse)
 
 1131    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
 
 1132      destination->extent.x,y,destination->extent.width,1,
 
 1133      destination->exception);
 
 1134    for (x=0; x < (ssize_t) destination->extent.width; x++)
 
 1136      PixelGetQuantumPixel(destination->image,destination->pixel_wands[
id][x],
 
 1137        destination_pixels);
 
 1138      destination_pixels+=(ptrdiff_t) GetPixelChannels(destination->image);
 
 1140    sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
 
 1141    if (sync == MagickFalse)
 
 1143    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
 
 1148#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1152        proceed=SetImageProgress(source_image,source->description,progress,
 
 1153          source->extent.height);
 
 1154        if (proceed == MagickFalse)
 
 1204WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
 
 1205  UpdateWandViewMethod update,
void *context)
 
 1216#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1224  assert(source != (WandView *) NULL);
 
 1225  assert(source->signature == MagickWandSignature);
 
 1226  if (update == (UpdateWandViewMethod) NULL)
 
 1227    return(MagickFalse);
 
 1228  source_image=source->wand->images;
 
 1229  status=SetImageStorageClass(source_image,DirectClass,source->exception);
 
 1230  if (status == MagickFalse)
 
 1231    return(MagickFalse);
 
 1234#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1235  height=(size_t) ((ssize_t) source->extent.height-source->extent.y);
 
 1236  #pragma omp parallel for schedule(static) shared(progress,status) \ 
 1237    magick_number_threads(source_image,source_image,height,1) 
 1239  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
 
 1242      id = GetOpenMPThreadId();
 
 1254      *magick_restrict pixels,
 
 1257    if (status == MagickFalse)
 
 1259    pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
 
 1260      source->extent.width,1,source->exception);
 
 1261    if (pixels == (Quantum *) NULL)
 
 1266    p=(
const Quantum *) pixels;
 
 1267    for (x=0; x < (ssize_t) source->extent.width; x++)
 
 1269      PixelSetQuantumPixel(source->image,p,source->pixel_wands[
id][x]);
 
 1270      p+=(ptrdiff_t) GetPixelChannels(source->image);
 
 1272    if (update(source,y,
id,context) == MagickFalse)
 
 1275    for (x=0; x < (ssize_t) source->extent.width; x++)
 
 1277      PixelGetQuantumPixel(source->image,source->pixel_wands[
id][x],q);
 
 1278      q+=(ptrdiff_t) GetPixelChannels(source->image);
 
 1280    sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
 
 1281    if (sync == MagickFalse)
 
 1283    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
 
 1288#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1292        proceed=SetImageProgress(source_image,source->description,progress,
 
 1293          source->extent.height);
 
 1294        if (proceed == MagickFalse)