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],
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;
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);
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+=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+=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+=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+=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+=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)
617 id = GetOpenMPThreadId();
619 assert(wand_view != (
WandView *) NULL);
620 assert(wand_view->signature == MagickWandSignature);
621 return(wand_view->pixel_wands[
id]);
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));
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));
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;
801 const ssize_t y,
const size_t width,
const size_t height)
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+=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+=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+=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+=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+=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+=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)