48#include "wand/studio.h"
49#include "wand/MagickWand.h"
50#include "wand/magick-wand-private.h"
52#include "magick/monitor-private.h"
53#include "magick/thread-private.h"
57#define WandViewId "WandView"
126 assert(wand_view != (
WandView *) NULL);
127 assert(wand_view->signature == WandSignature);
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,MaxTextExtent,
"%s-%.20g",
134 WandViewId,(
double) clone_view->id);
135 clone_view->description=ConstantString(wand_view->description);
136 clone_view->view=CloneCacheView(wand_view->view);
137 clone_view->extent=wand_view->extent;
138 clone_view->number_threads=wand_view->number_threads;
139 clone_view->exception=AcquireExceptionInfo();
140 InheritException(clone_view->exception,wand_view->exception);
141 for (i=0; i < (ssize_t) wand_view->number_threads; i++)
142 clone_view->pixel_wands[i]=ClonePixelWands((
const PixelWand **)
143 wand_view->pixel_wands[i],wand_view->extent.width);
144 clone_view->debug=wand_view->debug;
145 if (clone_view->debug != MagickFalse)
146 (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",clone_view->name);
147 clone_view->signature=WandSignature;
175 const size_t number_wands,
const size_t number_threads)
180 assert(pixel_wands != (
PixelWand ***) NULL);
181 for (i=0; i < (ssize_t) number_threads; i++)
182 if (pixel_wands[i] != (
PixelWand **) NULL)
183 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
184 pixel_wands=(
PixelWand ***) RelinquishMagickMemory(pixel_wands);
190 assert(wand_view != (
WandView *) NULL);
191 assert(wand_view->signature == WandSignature);
192 wand_view->pixel_wands=DestroyPixelsTLS(wand_view->pixel_wands,
193 wand_view->extent.width,wand_view->number_threads);
194 wand_view->view=DestroyCacheView(wand_view->view);
195 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
196 wand_view->signature=(~WandSignature);
197 RelinquishWandId(wand_view->id);
198 wand_view=(
WandView *) RelinquishMagickMemory(wand_view);
253WandExport MagickBooleanType DuplexTransferWandViewIterator(
WandView *source,
254 WandView *duplex,
WandView *destination,DuplexTransferWandViewMethod transfer,
271#if defined(MAGICKCORE_OPENMP_SUPPORT)
279 assert(source != (
WandView *) NULL);
280 assert(source->signature == WandSignature);
281 if (transfer == (DuplexTransferWandViewMethod) NULL)
283 source_image=source->wand->images;
284 duplex_image=duplex->wand->images;
285 destination_image=destination->wand->images;
286 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
290 exception=destination->exception;
291#if defined(MAGICKCORE_OPENMP_SUPPORT)
292 height=(size_t) (source->extent.height-source->extent.y);
293 #pragma omp parallel for schedule(static) shared(progress,status) \
294 magick_number_threads(source_image,destination_image,height,1)
296 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
299 id = GetOpenMPThreadId();
305 *magick_restrict duplex_indexes,
306 *magick_restrict indexes;
309 *magick_restrict duplex_pixels,
310 *magick_restrict pixels;
313 *magick_restrict destination_indexes;
319 *magick_restrict destination_pixels;
321 if (status == MagickFalse)
323 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
324 source->extent.width,1,source->exception);
325 if (pixels == (
const PixelPacket *) NULL)
330 indexes=GetCacheViewVirtualIndexQueue(source->view);
331 for (x=0; x < (ssize_t) source->extent.width; x++)
332 PixelSetQuantumColor(source->pixel_wands[
id][x],pixels+x);
333 if (source_image->colorspace == CMYKColorspace)
334 for (x=0; x < (ssize_t) source->extent.width; x++)
335 PixelSetBlackQuantum(source->pixel_wands[
id][x],
336 GetPixelBlack(indexes+x));
337 if (source_image->storage_class == PseudoClass)
338 for (x=0; x < (ssize_t) source->extent.width; x++)
339 PixelSetIndex(source->pixel_wands[
id][x],
340 GetPixelIndex(indexes+x));
341 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
342 duplex->extent.width,1,duplex->exception);
343 if (duplex_pixels == (
const PixelPacket *) NULL)
348 duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
349 for (x=0; x < (ssize_t) duplex->extent.width; x++)
350 PixelSetQuantumColor(duplex->pixel_wands[
id][x],duplex_pixels+x);
351 if (duplex_image->colorspace == CMYKColorspace)
352 for (x=0; x < (ssize_t) duplex->extent.width; x++)
353 PixelSetBlackQuantum(duplex->pixel_wands[
id][x],
354 GetPixelBlack(duplex_indexes+x));
355 if (duplex_image->storage_class == PseudoClass)
356 for (x=0; x < (ssize_t) duplex->extent.width; x++)
357 PixelSetIndex(duplex->pixel_wands[
id][x],
358 GetPixelIndex(duplex_indexes+x));
359 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
360 destination->extent.x,y,destination->extent.width,1,exception);
361 if (destination_pixels == (PixelPacket *) NULL)
366 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
367 for (x=0; x < (ssize_t) destination->extent.width; x++)
368 PixelSetQuantumColor(destination->pixel_wands[
id][x],
369 destination_pixels+x);
370 if (destination_image->colorspace == CMYKColorspace)
371 for (x=0; x < (ssize_t) destination->extent.width; x++)
372 PixelSetBlackQuantum(destination->pixel_wands[
id][x],
373 GetPixelBlack(destination_indexes+x));
374 if (destination_image->storage_class == PseudoClass)
375 for (x=0; x < (ssize_t) destination->extent.width; x++)
376 PixelSetIndex(destination->pixel_wands[
id][x],
377 GetPixelIndex(destination_indexes+x));
378 if (transfer(source,duplex,destination,y,
id,context) == MagickFalse)
380 for (x=0; x < (ssize_t) destination->extent.width; x++)
381 PixelGetQuantumColor(destination->pixel_wands[
id][x],
382 destination_pixels+x);
383 if (destination_image->colorspace == CMYKColorspace)
384 for (x=0; x < (ssize_t) destination->extent.width; x++)
385 SetPixelBlack(destination_indexes+x,PixelGetBlackQuantum(
386 destination->pixel_wands[
id][x]));
387 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
388 if (sync == MagickFalse)
390 InheritException(destination->exception,GetCacheViewException(
394 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
399#if defined(MAGICKCORE_OPENMP_SUPPORT)
403 proceed=SetImageProgress(source_image,source->description,progress,
404 source->extent.height);
405 if (proceed == MagickFalse)
438WandExport
char *GetWandViewException(
const WandView *wand_view,
439 ExceptionType *severity)
444 assert(wand_view != (
const WandView *) NULL);
445 assert(wand_view->signature == WandSignature);
446 if (wand_view->debug != MagickFalse)
447 (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",wand_view->name);
448 assert(severity != (ExceptionType *) NULL);
449 *severity=wand_view->exception->severity;
450 description=(
char *) AcquireQuantumMemory(2UL*MaxTextExtent,
451 sizeof(*description));
452 if (description == (
char *) NULL)
453 ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
456 if (wand_view->exception->reason != (
char *) NULL)
457 (void) CopyMagickString(description,GetLocaleExceptionMessage(
458 wand_view->exception->severity,wand_view->exception->reason),
460 if (wand_view->exception->description != (
char *) NULL)
462 (void) ConcatenateMagickString(description,
" (",MaxTextExtent);
463 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
464 wand_view->exception->severity,wand_view->exception->description),
466 (void) ConcatenateMagickString(description,
")",MaxTextExtent);
493WandExport RectangleInfo GetWandViewExtent(
const WandView *wand_view)
495 assert(wand_view != (
WandView *) NULL);
496 assert(wand_view->signature == WandSignature);
497 return(wand_view->extent);
543WandExport MagickBooleanType GetWandViewIterator(
WandView *source,
544 GetWandViewMethod get,
void *context)
555#if defined(MAGICKCORE_OPENMP_SUPPORT)
563 assert(source != (
WandView *) NULL);
564 assert(source->signature == WandSignature);
565 if (get == (GetWandViewMethod) NULL)
567 source_image=source->wand->images;
570#if defined(MAGICKCORE_OPENMP_SUPPORT)
571 height=(size_t) (source->extent.height-source->extent.y);
572 #pragma omp parallel for schedule(static) shared(progress,status) \
573 magick_number_threads(source_image,source_image,height,1)
575 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
578 id = GetOpenMPThreadId();
589 if (status == MagickFalse)
591 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
592 source->extent.width,1,source->exception);
593 if (pixels == (
const PixelPacket *) NULL)
598 indexes=GetCacheViewVirtualIndexQueue(source->view);
599 for (x=0; x < (ssize_t) source->extent.width; x++)
600 PixelSetQuantumColor(source->pixel_wands[
id][x],pixels+x);
601 if (source_image->colorspace == CMYKColorspace)
602 for (x=0; x < (ssize_t) source->extent.width; x++)
603 PixelSetBlackQuantum(source->pixel_wands[
id][x],
604 GetPixelBlack(indexes+x));
605 if (source_image->storage_class == PseudoClass)
606 for (x=0; x < (ssize_t) source->extent.width; x++)
607 PixelSetIndex(source->pixel_wands[
id][x],
608 GetPixelIndex(indexes+x));
609 if (get(source,y,
id,context) == MagickFalse)
611 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
616#if defined(MAGICKCORE_OPENMP_SUPPORT)
620 proceed=SetImageProgress(source_image,source->description,progress,
621 source->extent.height);
622 if (proceed == MagickFalse)
654 id = GetOpenMPThreadId();
656 assert(wand_view != (
WandView *) NULL);
657 assert(wand_view->signature == WandSignature);
658 return(wand_view->pixel_wands[
id]);
685 assert(wand_view != (
WandView *) NULL);
686 assert(wand_view->signature == WandSignature);
687 return(wand_view->wand);
713WandExport MagickBooleanType IsWandView(
const WandView *wand_view)
718 if (wand_view == (
const WandView *) NULL)
720 if (wand_view->signature != WandSignature)
722 length=strlen(WandViewId);
723 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
752static PixelWand ***AcquirePixelsTLS(
const size_t number_wands,
753 const size_t number_threads)
761 pixel_wands=(
PixelWand ***) AcquireQuantumMemory(number_threads,
762 sizeof(*pixel_wands));
765 (void) memset(pixel_wands,0,number_threads*
sizeof(*pixel_wands));
766 for (i=0; i < (ssize_t) number_threads; i++)
768 pixel_wands[i]=NewPixelWands(number_wands);
769 if (pixel_wands[i] == (
PixelWand **) NULL)
770 return(DestroyPixelsTLS(pixel_wands,number_wands,number_threads));
781 assert(wand->signature == WandSignature);
782 wand_view=(
WandView *) AcquireCriticalMemory(
sizeof(*wand_view));
783 (void) memset(wand_view,0,
sizeof(*wand_view));
784 wand_view->id=AcquireWandId();
785 (void) FormatLocaleString(wand_view->name,MaxTextExtent,
"%s-%.20g",
786 WandViewId,(
double) wand_view->id);
787 wand_view->description=ConstantString(
"WandView");
788 wand_view->wand=wand;
789 wand_view->exception=AcquireExceptionInfo();
790 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,
791 wand_view->exception);
792 wand_view->extent.width=wand->images->columns;
793 wand_view->extent.height=wand->images->rows;
794 wand_view->number_threads=GetOpenMPMaximumThreads();
795 wand_view->pixel_wands=AcquirePixelsTLS(wand_view->extent.width,
796 wand_view->number_threads);
797 if (wand_view->pixel_wands == (
PixelWand ***) NULL)
798 ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
799 GetExceptionMessage(errno));
800 wand_view->debug=IsEventLogging();
801 wand_view->signature=WandSignature;
833 const ssize_t y,
const size_t width,
const size_t height)
839 assert(wand->signature == WandSignature);
840 wand_view=(
WandView *) AcquireCriticalMemory(
sizeof(*wand_view));
841 (void) memset(wand_view,0,
sizeof(*wand_view));
842 wand_view->id=AcquireWandId();
843 (void) FormatLocaleString(wand_view->name,MaxTextExtent,
"%s-%.20g",
844 WandViewId,(
double) wand_view->id);
845 wand_view->description=ConstantString(
"WandView");
846 wand_view->exception=AcquireExceptionInfo();
847 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,
848 wand_view->exception);
849 wand_view->wand=wand;
850 wand_view->extent.width=width;
851 wand_view->extent.height=height;
852 wand_view->extent.x=x;
853 wand_view->extent.y=y;
854 wand_view->number_threads=GetOpenMPMaximumThreads();
855 wand_view->pixel_wands=AcquirePixelsTLS(wand_view->extent.width,
856 wand_view->number_threads);
857 if (wand_view->pixel_wands == (
PixelWand ***) NULL)
858 ThrowWandFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed",
859 GetExceptionMessage(errno));
860 wand_view->debug=IsEventLogging();
861 wand_view->signature=WandSignature;
889MagickExport
void SetWandViewDescription(
WandView *wand_view,
890 const char *description)
892 assert(wand_view != (
WandView *) NULL);
893 assert(wand_view->signature == WandSignature);
894 wand_view->description=ConstantString(description);
941WandExport MagickBooleanType SetWandViewIterator(
WandView *destination,
942 SetWandViewMethod set,
void *context)
956#if defined(MAGICKCORE_OPENMP_SUPPORT)
964 assert(destination != (
WandView *) NULL);
965 assert(destination->signature == WandSignature);
966 if (set == (SetWandViewMethod) NULL)
968 destination_image=destination->wand->images;
969 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
973 exception=destination->exception;
974#if defined(MAGICKCORE_OPENMP_SUPPORT)
975 height=(size_t) (destination->extent.height-destination->extent.y);
976 #pragma omp parallel for schedule(static) shared(progress,status) \
977 magick_number_threads(destination_image,destination_image,height,1)
979 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
982 id = GetOpenMPThreadId();
988 *magick_restrict indexes;
994 *magick_restrict pixels;
996 if (status == MagickFalse)
998 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
999 y,destination->extent.width,1,exception);
1000 if (pixels == (PixelPacket *) NULL)
1002 InheritException(destination->exception,GetCacheViewException(
1003 destination->view));
1007 indexes=GetCacheViewAuthenticIndexQueue(destination->view);
1008 if (set(destination,y,
id,context) == MagickFalse)
1010 for (x=0; x < (ssize_t) destination->extent.width; x++)
1011 PixelGetQuantumColor(destination->pixel_wands[
id][x],pixels+x);
1012 if (destination_image->colorspace == CMYKColorspace)
1013 for (x=0; x < (ssize_t) destination->extent.width; x++)
1014 SetPixelBlack(indexes+x,PixelGetBlackQuantum(
1015 destination->pixel_wands[
id][x]));
1016 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1017 if (sync == MagickFalse)
1019 InheritException(destination->exception,GetCacheViewException(
1020 destination->view));
1023 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
1028#if defined(MAGICKCORE_OPENMP_SUPPORT)
1032 proceed=SetImageProgress(destination_image,destination->description,
1033 progress,destination->extent.height);
1034 if (proceed == MagickFalse)
1066MagickExport
void SetWandViewThreads(
WandView *image_view,
1067 const size_t number_threads)
1069 assert(image_view != (
WandView *) NULL);
1070 assert(image_view->signature == MagickCoreSignature);
1071 image_view->number_threads=number_threads;
1072 if (number_threads > (
size_t) GetMagickResourceLimit(ThreadResource))
1073 image_view->number_threads=GetOpenMPMaximumThreads();
1124WandExport MagickBooleanType TransferWandViewIterator(
WandView *source,
1125 WandView *destination,TransferWandViewMethod transfer,
void *context)
1140#if defined(MAGICKCORE_OPENMP_SUPPORT)
1148 assert(source != (
WandView *) NULL);
1149 assert(source->signature == WandSignature);
1150 if (transfer == (TransferWandViewMethod) NULL)
1151 return(MagickFalse);
1152 source_image=source->wand->images;
1153 destination_image=destination->wand->images;
1154 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
1155 return(MagickFalse);
1158 exception=destination->exception;
1159#if defined(MAGICKCORE_OPENMP_SUPPORT)
1160 height=(size_t) (source->extent.height-source->extent.y);
1161 #pragma omp parallel for schedule(static) shared(progress,status) \
1162 magick_number_threads(source_image,destination_image,height,1)
1164 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1167 id = GetOpenMPThreadId();
1173 *magick_restrict indexes;
1176 *magick_restrict pixels;
1179 *magick_restrict destination_indexes;
1185 *magick_restrict destination_pixels;
1187 if (status == MagickFalse)
1189 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1190 source->extent.width,1,source->exception);
1191 if (pixels == (
const PixelPacket *) NULL)
1196 indexes=GetCacheViewVirtualIndexQueue(source->view);
1197 for (x=0; x < (ssize_t) source->extent.width; x++)
1198 PixelSetQuantumColor(source->pixel_wands[
id][x],pixels+x);
1199 if (source_image->colorspace == CMYKColorspace)
1200 for (x=0; x < (ssize_t) source->extent.width; x++)
1201 PixelSetBlackQuantum(source->pixel_wands[
id][x],
1202 GetPixelBlack(indexes+x));
1203 if (source_image->storage_class == PseudoClass)
1204 for (x=0; x < (ssize_t) source->extent.width; x++)
1205 PixelSetIndex(source->pixel_wands[
id][x],
1206 GetPixelIndex(indexes+x));
1207 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1208 destination->extent.x,y,destination->extent.width,1,exception);
1209 if (destination_pixels == (PixelPacket *) NULL)
1214 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
1215 for (x=0; x < (ssize_t) destination->extent.width; x++)
1216 PixelSetQuantumColor(destination->pixel_wands[
id][x],pixels+x);
1217 if (destination_image->colorspace == CMYKColorspace)
1218 for (x=0; x < (ssize_t) destination->extent.width; x++)
1219 PixelSetBlackQuantum(destination->pixel_wands[
id][x],
1220 GetPixelBlack(indexes+x));
1221 if (destination_image->storage_class == PseudoClass)
1222 for (x=0; x < (ssize_t) destination->extent.width; x++)
1223 PixelSetIndex(destination->pixel_wands[
id][x],
1224 GetPixelIndex(indexes+x));
1225 if (transfer(source,destination,y,
id,context) == MagickFalse)
1227 for (x=0; x < (ssize_t) destination->extent.width; x++)
1228 PixelGetQuantumColor(destination->pixel_wands[
id][x],
1229 destination_pixels+x);
1230 if (destination_image->colorspace == CMYKColorspace)
1231 for (x=0; x < (ssize_t) destination->extent.width; x++)
1232 SetPixelBlack(destination_indexes+x,PixelGetBlackQuantum(
1233 destination->pixel_wands[
id][x]));
1234 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1235 if (sync == MagickFalse)
1237 InheritException(destination->exception,GetCacheViewException(
1241 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1246#if defined(MAGICKCORE_OPENMP_SUPPORT)
1250 proceed=SetImageProgress(source_image,source->description,progress,
1251 source->extent.height);
1252 if (proceed == MagickFalse)
1302WandExport MagickBooleanType UpdateWandViewIterator(
WandView *source,
1303 UpdateWandViewMethod update,
void *context)
1317#if defined(MAGICKCORE_OPENMP_SUPPORT)
1325 assert(source != (
WandView *) NULL);
1326 assert(source->signature == WandSignature);
1327 if (update == (UpdateWandViewMethod) NULL)
1328 return(MagickFalse);
1329 source_image=source->wand->images;
1330 if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
1331 return(MagickFalse);
1334 exception=source->exception;
1335#if defined(MAGICKCORE_OPENMP_SUPPORT)
1336 height=(size_t) (source->extent.height-source->extent.y);
1337 #pragma omp parallel for schedule(static) shared(progress,status) \
1338 magick_number_threads(source_image,source_image,height,1)
1340 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1343 id = GetOpenMPThreadId();
1346 *magick_restrict indexes;
1352 *magick_restrict pixels;
1354 if (status == MagickFalse)
1356 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1357 source->extent.width,1,exception);
1358 if (pixels == (PixelPacket *) NULL)
1360 InheritException(source->exception,GetCacheViewException(
1365 indexes=GetCacheViewAuthenticIndexQueue(source->view);
1366 for (x=0; x < (ssize_t) source->extent.width; x++)
1367 PixelSetQuantumColor(source->pixel_wands[
id][x],pixels+x);
1368 if (source_image->colorspace == CMYKColorspace)
1369 for (x=0; x < (ssize_t) source->extent.width; x++)
1370 PixelSetBlackQuantum(source->pixel_wands[
id][x],
1371 GetPixelBlack(indexes+x));
1372 if (update(source,y,
id,context) == MagickFalse)
1374 for (x=0; x < (ssize_t) source->extent.width; x++)
1375 PixelGetQuantumColor(source->pixel_wands[
id][x],pixels+x);
1376 if (source_image->colorspace == CMYKColorspace)
1377 for (x=0; x < (ssize_t) source->extent.width; x++)
1378 SetPixelBlack(indexes+x,PixelGetBlackQuantum(
1379 source->pixel_wands[
id][x]));
1380 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1382 InheritException(source->exception,GetCacheViewException(source->view));
1385 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1390#if defined(MAGICKCORE_OPENMP_SUPPORT)
1394 proceed=SetImageProgress(source_image,source->description,progress,
1395 source->extent.height);
1396 if (proceed == MagickFalse)