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->image=DestroyImage(wand_view->image);
196 wand_view->view=DestroyCacheView(wand_view->view);
197 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
198 wand_view->signature=(~MagickWandSignature);
199 RelinquishWandId(wand_view->id);
200 wand_view=(
WandView *) RelinquishMagickMemory(wand_view);
255 WandExport MagickBooleanType DuplexTransferWandViewIterator(
WandView *source,
256 WandView *duplex,
WandView *destination,DuplexTransferWandViewMethod transfer,
269 #if defined(MAGICKCORE_OPENMP_SUPPORT)
277 assert(source != (
WandView *) NULL);
278 assert(source->signature == MagickWandSignature);
279 if (transfer == (DuplexTransferWandViewMethod) NULL)
281 source_image=source->wand->images;
282 destination_image=destination->wand->images;
283 status=SetImageStorageClass(destination_image,DirectClass,
284 destination->exception);
285 if (status == MagickFalse)
289 #if defined(MAGICKCORE_OPENMP_SUPPORT)
290 height=source->extent.height-source->extent.y;
291 #pragma omp parallel for schedule(static) shared(progress,status) \
292 magick_number_threads(source_image,destination_image,height,1)
294 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
297 id = GetOpenMPThreadId();
303 *magick_restrict duplex_pixels,
304 *magick_restrict pixels;
310 *magick_restrict destination_pixels;
312 if (status == MagickFalse)
314 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
315 source->extent.width,1,source->exception);
316 if (pixels == (
const Quantum *) NULL)
321 for (x=0; x < (ssize_t) source->extent.width; x++)
323 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
324 pixels+=GetPixelChannels(source->image);
326 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
327 duplex->extent.width,1,duplex->exception);
328 if (duplex_pixels == (
const Quantum *) NULL)
333 for (x=0; x < (ssize_t) duplex->extent.width; x++)
335 PixelSetQuantumPixel(duplex->image,duplex_pixels,
336 duplex->pixel_wands[
id][x]);
337 duplex_pixels+=GetPixelChannels(duplex->image);
339 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
340 destination->extent.x,y,destination->extent.width,1,
341 destination->exception);
342 if (destination_pixels == (Quantum *) NULL)
347 for (x=0; x < (ssize_t) destination->extent.width; x++)
349 PixelSetQuantumPixel(destination->image,destination_pixels,
350 destination->pixel_wands[
id][x]);
351 destination_pixels+=GetPixelChannels(destination->image);
353 if (transfer(source,duplex,destination,y,
id,context) == MagickFalse)
355 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
356 destination->extent.x,y,destination->extent.width,1,
357 destination->exception);
358 for (x=0; x < (ssize_t) destination->extent.width; x++)
360 PixelGetQuantumPixel(destination->image,destination->pixel_wands[
id][x],
362 destination_pixels+=GetPixelChannels(destination->image);
364 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
365 if (sync == MagickFalse)
367 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
372 #if defined(MAGICKCORE_OPENMP_SUPPORT)
376 proceed=SetImageProgress(source_image,source->description,progress,
377 source->extent.height);
378 if (proceed == MagickFalse)
411 WandExport
char *GetWandViewException(
const WandView *wand_view,
412 ExceptionType *severity)
417 assert(wand_view != (
const WandView *) NULL);
418 assert(wand_view->signature == MagickWandSignature);
419 if (wand_view->debug != MagickFalse)
420 (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",wand_view->name);
421 assert(severity != (ExceptionType *) NULL);
422 *severity=wand_view->exception->severity;
423 description=(
char *) AcquireQuantumMemory(2UL*MagickPathExtent,
424 sizeof(*description));
425 if (description == (
char *) NULL)
426 ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
429 if (wand_view->exception->reason != (
char *) NULL)
430 (
void) CopyMagickString(description,GetLocaleExceptionMessage(
431 wand_view->exception->severity,wand_view->exception->reason),
433 if (wand_view->exception->description != (
char *) NULL)
435 (void) ConcatenateMagickString(description,
" (",MagickPathExtent);
436 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
437 wand_view->exception->severity,wand_view->exception->description),
439 (void) ConcatenateMagickString(description,
")",MagickPathExtent);
466 WandExport RectangleInfo GetWandViewExtent(
const WandView *wand_view)
468 assert(wand_view != (
WandView *) NULL);
469 assert(wand_view->signature == MagickWandSignature);
470 return(wand_view->extent);
516 WandExport MagickBooleanType GetWandViewIterator(
WandView *source,
517 GetWandViewMethod get,
void *context)
528 #if defined(MAGICKCORE_OPENMP_SUPPORT)
536 assert(source != (
WandView *) NULL);
537 assert(source->signature == MagickWandSignature);
538 if (get == (GetWandViewMethod) NULL)
540 source_image=source->wand->images;
543 #if defined(MAGICKCORE_OPENMP_SUPPORT)
544 height=source->extent.height-source->extent.y;
545 #pragma omp parallel for schedule(static) shared(progress,status) \
546 magick_number_threads(source_image,source_image,height,1)
548 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
551 id = GetOpenMPThreadId();
559 if (status == MagickFalse)
561 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
562 source->extent.width,1,source->exception);
563 if (pixels == (
const Quantum *) NULL)
568 for (x=0; x < (ssize_t) source->extent.width; x++)
570 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
571 pixels+=GetPixelChannels(source->image);
573 if (get(source,y,
id,context) == MagickFalse)
575 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
580 #if defined(MAGICKCORE_OPENMP_SUPPORT)
584 proceed=SetImageProgress(source_image,source->description,progress,
585 source->extent.height);
586 if (proceed == MagickFalse)
618 id = GetOpenMPThreadId();
620 assert(wand_view != (
WandView *) NULL);
621 assert(wand_view->signature == MagickWandSignature);
622 return(wand_view->pixel_wands[
id]);
649 assert(wand_view != (
WandView *) NULL);
650 assert(wand_view->signature == MagickWandSignature);
651 return(wand_view->wand);
677 WandExport MagickBooleanType IsWandView(
const WandView *wand_view)
682 if (wand_view == (
const WandView *) NULL)
684 if (wand_view->signature != MagickWandSignature)
686 length=strlen(WandViewId);
687 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
716 static PixelWand ***AcquirePixelsTLS(
const size_t number_wands)
727 number_threads=GetOpenMPMaximumThreads();
728 pixel_wands=(
PixelWand ***) AcquireQuantumMemory(number_threads,
729 sizeof(*pixel_wands));
732 (void) memset(pixel_wands,0,number_threads*
sizeof(*pixel_wands));
733 for (i=0; i < (ssize_t) number_threads; i++)
735 pixel_wands[i]=NewPixelWands(number_wands);
736 if (pixel_wands[i] == (
PixelWand **) NULL)
737 return(DestroyPixelsTLS(pixel_wands,number_wands));
751 assert(wand->signature == MagickWandSignature);
752 wand_view=(
WandView *) AcquireCriticalMemory(
sizeof(*wand_view));
753 (void) memset(wand_view,0,
sizeof(*wand_view));
754 wand_view->id=AcquireWandId();
755 (void) FormatLocaleString(wand_view->name,MagickPathExtent,
"%s-%.20g",
756 WandViewId,(
double) wand_view->id);
757 wand_view->description=ConstantString(
"WandView");
758 wand_view->wand=wand;
759 exception=AcquireExceptionInfo();
760 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
761 wand_view->extent.width=wand->images->columns;
762 wand_view->extent.height=wand->images->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;
858 MagickExport
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);
910 WandExport 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=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();
958 *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)
1046 WandExport 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=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();
1093 *magick_restrict pixels;
1099 *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)
1204 WandExport 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=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();
1251 *magick_restrict pixels;
1253 if (status == MagickFalse)
1255 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1256 source->extent.width,1,source->exception);
1257 if (pixels == (Quantum *) NULL)
1262 for (x=0; x < (ssize_t) source->extent.width; x++)
1264 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[
id][x]);
1265 pixels+=GetPixelChannels(source->image);
1267 if (update(source,y,
id,context) == MagickFalse)
1269 for (x=0; x < (ssize_t) source->extent.width; x++)
1271 PixelGetQuantumPixel(source->image,source->pixel_wands[
id][x],pixels);
1272 pixels+=GetPixelChannels(source->image);
1274 sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1275 if (sync == MagickFalse)
1277 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1282 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1286 proceed=SetImageProgress(source_image,source->description,progress,
1287 source->extent.height);
1288 if (proceed == MagickFalse)