42#include "magick/studio.h"
43#include "magick/accelerate-private.h"
44#include "magick/artifact.h"
45#include "magick/blob.h"
46#include "magick/cache.h"
47#include "magick/cache-view.h"
48#include "magick/channel.h"
49#include "magick/color.h"
50#include "magick/color-private.h"
51#include "magick/draw.h"
52#include "magick/exception.h"
53#include "magick/exception-private.h"
54#include "magick/gem.h"
55#include "magick/image.h"
56#include "magick/image-private.h"
57#include "magick/list.h"
58#include "magick/memory_.h"
59#include "magick/memory-private.h"
60#include "magick/magick.h"
61#include "magick/pixel-private.h"
62#include "magick/property.h"
63#include "magick/monitor.h"
64#include "magick/monitor-private.h"
65#include "magick/nt-base-private.h"
66#include "magick/pixel.h"
67#include "magick/pixel-private.h"
68#include "magick/option.h"
69#include "magick/resample.h"
70#include "magick/resample-private.h"
71#include "magick/resize.h"
72#include "magick/resize-private.h"
73#include "magick/resource_.h"
74#include "magick/string_.h"
75#include "magick/string-private.h"
76#include "magick/thread-private.h"
77#include "magick/token.h"
78#include "magick/utility.h"
79#include "magick/version.h"
80#if defined(MAGICKCORE_LQR_DELEGATE)
98 ResizeWeightingFunctionType
110 I0(MagickRealType x),
111 BesselOrderOne(MagickRealType),
148static MagickRealType Blackman(
const MagickRealType x,
158 const MagickRealType cosine = cos((
double) (MagickPI*x));
159 magick_unreferenced(resize_filter);
160 return(0.34+cosine*(0.5+cosine*0.16));
163static MagickRealType Bohman(
const MagickRealType x,
174 const double cosine = cos((
double) (MagickPI*x));
175 const double sine = sqrt(1.0-cosine*cosine);
176 magick_unreferenced(resize_filter);
177 return((MagickRealType) ((1.0-x)*cosine+(1.0/MagickPI)*sine));
180static MagickRealType Box(
const MagickRealType magick_unused(x),
188 magick_unreferenced(x);
189 magick_unreferenced(resize_filter);
194static MagickRealType Cosine(
const MagickRealType x,
201 magick_unreferenced(resize_filter);
202 return((MagickRealType) cos((
double) (MagickPI2*x)));
205static MagickRealType CubicBC(
const MagickRealType x,
238 return(resize_filter->coefficient[0]+x*(x*
239 (resize_filter->coefficient[1]+x*resize_filter->coefficient[2])));
241 return(resize_filter->coefficient[3]+x*(resize_filter->coefficient[4]+x*
242 (resize_filter->coefficient[5]+x*resize_filter->coefficient[6])));
246static MagickRealType Gaussian(
const MagickRealType x,
279 return(exp((
double)(-resize_filter->coefficient[1]*x*x)));
282static MagickRealType Hanning(
const MagickRealType x,
289 const MagickRealType cosine = cos((
double) (MagickPI*x));
290 magick_unreferenced(resize_filter);
291 return(0.5+0.5*cosine);
294static MagickRealType Hamming(
const MagickRealType x,
301 const MagickRealType cosine = cos((
double) (MagickPI*x));
302 magick_unreferenced(resize_filter);
303 return(0.54+0.46*cosine);
306static MagickRealType Jinc(
const MagickRealType x,
317 magick_unreferenced(resize_filter);
320 return((MagickRealType) (0.5*MagickPI));
321 return(BesselOrderOne((MagickRealType) MagickPI*x)/x);
324static MagickRealType Kaiser(
const MagickRealType x,
339 return(resize_filter->coefficient[1]*I0(resize_filter->coefficient[0]*
340 sqrt((
double) (1.0-x*x))));
343static MagickRealType Lagrange(
const MagickRealType x,
366 if (x > resize_filter->support)
368 order=(ssize_t) (2.0*resize_filter->window_support);
369 n=(ssize_t) (resize_filter->window_support+x);
371 for (i=0; i < order; i++)
373 value*=(n-i-x)/(n-i);
377static MagickRealType Quadratic(
const MagickRealType x,
383 magick_unreferenced(resize_filter);
388 return(0.5*(x-1.5)*(x-1.5));
392static MagickRealType Sinc(
const MagickRealType x,
399 magick_unreferenced(resize_filter);
403 const MagickRealType alpha=(MagickRealType) (MagickPI*x);
404 return(sin((
double) alpha)/alpha);
406 return((MagickRealType) 1.0);
409static MagickRealType SincFast(
const MagickRealType x,
436 magick_unreferenced(resize_filter);
440 const MagickRealType alpha=(MagickRealType) (MagickPI*x);
441 return(sin((
double) alpha)/alpha);
447 const MagickRealType xx = x*x;
448#if MAGICKCORE_QUANTUM_DEPTH <= 8
452 const double c0 = 0.173610016489197553621906385078711564924e-2L;
453 const double c1 = -0.384186115075660162081071290162149315834e-3L;
454 const double c2 = 0.393684603287860108352720146121813443561e-4L;
455 const double c3 = -0.248947210682259168029030370205389323899e-5L;
456 const double c4 = 0.107791837839662283066379987646635416692e-6L;
457 const double c5 = -0.324874073895735800961260474028013982211e-8L;
458 const double c6 = 0.628155216606695311524920882748052490116e-10L;
459 const double c7 = -0.586110644039348333520104379959307242711e-12L;
461 c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
462 return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p);
463#elif MAGICKCORE_QUANTUM_DEPTH <= 16
467 const double c0 = 0.173611107357320220183368594093166520811e-2L;
468 const double c1 = -0.384240921114946632192116762889211361285e-3L;
469 const double c2 = 0.394201182359318128221229891724947048771e-4L;
470 const double c3 = -0.250963301609117217660068889165550534856e-5L;
471 const double c4 = 0.111902032818095784414237782071368805120e-6L;
472 const double c5 = -0.372895101408779549368465614321137048875e-8L;
473 const double c6 = 0.957694196677572570319816780188718518330e-10L;
474 const double c7 = -0.187208577776590710853865174371617338991e-11L;
475 const double c8 = 0.253524321426864752676094495396308636823e-13L;
476 const double c9 = -0.177084805010701112639035485248501049364e-15L;
478 c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*(c7+xx*(c8+xx*c9))))))));
479 return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p);
484 const double c0 = 0.173611111110910715186413700076827593074e-2L;
485 const double c1 = -0.289105544717893415815859968653611245425e-3L;
486 const double c2 = 0.206952161241815727624413291940849294025e-4L;
487 const double c3 = -0.834446180169727178193268528095341741698e-6L;
488 const double c4 = 0.207010104171026718629622453275917944941e-7L;
489 const double c5 = -0.319724784938507108101517564300855542655e-9L;
490 const double c6 = 0.288101675249103266147006509214934493930e-11L;
491 const double c7 = -0.118218971804934245819960233886876537953e-13L;
493 c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
494 const double d0 = 1.0L;
495 const double d1 = 0.547981619622284827495856984100563583948e-1L;
496 const double d2 = 0.134226268835357312626304688047086921806e-2L;
497 const double d3 = 0.178994697503371051002463656833597608689e-4L;
498 const double d4 = 0.114633394140438168641246022557689759090e-6L;
499 const double q = d0+xx*(d1+xx*(d2+xx*(d3+xx*d4)));
500 return((MagickRealType) ((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)/q*p));
505static MagickRealType Triangle(
const MagickRealType x,
513 magick_unreferenced(resize_filter);
520static MagickRealType Welsh(
const MagickRealType x,
526 magick_unreferenced(resize_filter);
720 const FilterTypes filter,
const MagickRealType blur,
721 const MagickBooleanType cylindrical,
ExceptionInfo *exception)
756 }
const mapping[SentinelFilter] =
758 { UndefinedFilter, BoxFilter },
759 { PointFilter, BoxFilter },
760 { BoxFilter, BoxFilter },
761 { TriangleFilter, BoxFilter },
762 { HermiteFilter, BoxFilter },
763 { SincFastFilter, HanningFilter },
764 { SincFastFilter, HammingFilter },
765 { SincFastFilter, BlackmanFilter },
766 { GaussianFilter, BoxFilter },
767 { QuadraticFilter, BoxFilter },
768 { CubicFilter, BoxFilter },
769 { CatromFilter, BoxFilter },
770 { MitchellFilter, BoxFilter },
771 { JincFilter, BoxFilter },
772 { SincFilter, BoxFilter },
773 { SincFastFilter, BoxFilter },
774 { SincFastFilter, KaiserFilter },
775 { LanczosFilter, WelshFilter },
776 { SincFastFilter, CubicFilter },
777 { SincFastFilter, BohmanFilter },
778 { SincFastFilter, TriangleFilter },
779 { LagrangeFilter, BoxFilter },
780 { LanczosFilter, LanczosFilter },
781 { LanczosSharpFilter, LanczosSharpFilter },
782 { Lanczos2Filter, Lanczos2Filter },
783 { Lanczos2SharpFilter, Lanczos2SharpFilter },
784 { RobidouxFilter, BoxFilter },
785 { RobidouxSharpFilter, BoxFilter },
786 { LanczosFilter, CosineFilter },
787 { SplineFilter, BoxFilter },
788 { LanczosRadiusFilter, LanczosFilter },
811 ResizeWeightingFunctionType weightingFunctionType;
812 }
const filters[SentinelFilter] =
819 { Box, 0.5, 0.5, 0.0, 0.0, BoxWeightingFunction },
820 { Box, 0.0, 0.5, 0.0, 0.0, BoxWeightingFunction },
821 { Box, 0.5, 0.5, 0.0, 0.0, BoxWeightingFunction },
822 { Triangle, 1.0, 1.0, 0.0, 0.0, TriangleWeightingFunction },
823 { CubicBC, 1.0, 1.0, 0.0, 0.0, CubicBCWeightingFunction },
824 { Hanning, 1.0, 1.0, 0.0, 0.0, HanningWeightingFunction },
825 { Hamming, 1.0, 1.0, 0.0, 0.0, HammingWeightingFunction },
826 { Blackman, 1.0, 1.0, 0.0, 0.0, BlackmanWeightingFunction },
827 { Gaussian, 2.0, 1.5, 0.0, 0.0, GaussianWeightingFunction },
828 { Quadratic, 1.5, 1.5, 0.0, 0.0, QuadraticWeightingFunction },
829 { CubicBC, 2.0, 2.0, 1.0, 0.0, CubicBCWeightingFunction },
830 { CubicBC, 2.0, 1.0, 0.0, 0.5, CubicBCWeightingFunction },
831 { CubicBC, 2.0, 8.0/7.0, 1./3., 1./3., CubicBCWeightingFunction },
832 { Jinc, 3.0, 1.2196698912665045, 0.0, 0.0, JincWeightingFunction },
833 { Sinc, 4.0, 1.0, 0.0, 0.0, SincWeightingFunction },
834 { SincFast, 4.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
835 { Kaiser, 1.0, 1.0, 0.0, 0.0, KaiserWeightingFunction },
836 { Welsh, 1.0, 1.0, 0.0, 0.0, WelshWeightingFunction },
837 { CubicBC, 2.0, 2.0, 1.0, 0.0, CubicBCWeightingFunction },
838 { Bohman, 1.0, 1.0, 0.0, 0.0, BohmanWeightingFunction },
839 { Triangle, 1.0, 1.0, 0.0, 0.0, TriangleWeightingFunction },
840 { Lagrange, 2.0, 1.0, 0.0, 0.0, LagrangeWeightingFunction },
841 { SincFast, 3.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
842 { SincFast, 3.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
843 { SincFast, 2.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
844 { SincFast, 2.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
846 { CubicBC, 2.0, 1.1685777620836932,
847 0.37821575509399867, 0.31089212245300067, CubicBCWeightingFunction },
849 { CubicBC, 2.0, 1.105822933719019,
850 0.2620145123990142, 0.3689927438004929, CubicBCWeightingFunction },
851 { Cosine, 1.0, 1.0, 0.0, 0.0, CosineWeightingFunction },
852 { CubicBC, 2.0, 2.0, 1.0, 0.0, CubicBCWeightingFunction },
853 { SincFast, 3.0, 1.0, 0.0, 0.0, SincFastWeightingFunction },
890 assert(image != (
const Image *) NULL);
891 assert(image->signature == MagickCoreSignature);
892 assert(UndefinedFilter < filter && filter < SentinelFilter);
894 assert(exception->signature == MagickCoreSignature);
895 if (IsEventLogging() != MagickFalse)
896 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
898 resize_filter=(
ResizeFilter *) AcquireMagickMemory(
sizeof(*resize_filter));
900 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
901 (void) memset(resize_filter,0,
sizeof(*resize_filter));
905 filter_type=mapping[filter].filter;
906 window_type=mapping[filter].window;
907 resize_filter->blur = blur;
909 if ((cylindrical != MagickFalse) && (filter_type == SincFastFilter) &&
910 (filter != SincFastFilter))
911 filter_type=JincFilter;
914 artifact=GetImageArtifact(image,
"filter:filter");
915 if (artifact != (
const char *) NULL)
920 option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
921 if ((UndefinedFilter < option) && (option < SentinelFilter))
923 filter_type=(FilterTypes) option;
924 window_type=BoxFilter;
927 artifact=GetImageArtifact(image,
"filter:window");
928 if (artifact != (
const char *) NULL)
930 option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
931 if ((UndefinedFilter < option) && (option < SentinelFilter))
932 window_type=(FilterTypes) option;
938 artifact=GetImageArtifact(image,
"filter:window");
939 if (artifact != (
const char *) NULL)
944 option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
945 if ((UndefinedFilter < option) && (option < SentinelFilter))
947 filter_type=cylindrical != MagickFalse ?
948 JincFilter : SincFastFilter;
949 window_type=(FilterTypes) option;
955 resize_filter->filter=filters[filter_type].function;
956 resize_filter->support=filters[filter_type].support;
957 resize_filter->filterWeightingType=filters[filter_type].weightingFunctionType;
958 resize_filter->window=filters[window_type].function;
959 resize_filter->windowWeightingType=filters[window_type].weightingFunctionType;
960 resize_filter->scale=filters[window_type].scale;
961 resize_filter->signature=MagickCoreSignature;
964 if (cylindrical != MagickFalse)
969 resize_filter->support=(MagickRealType) MagickSQ1_2;
972 case LanczosSharpFilter:
974 case Lanczos2SharpFilter:
975 case LanczosRadiusFilter:
976 resize_filter->filter=filters[JincFilter].function;
977 resize_filter->window=filters[JincFilter].function;
978 resize_filter->scale=filters[JincFilter].scale;
987 case LanczosSharpFilter:
988 resize_filter->blur *= (MagickRealType) 0.9812505644269356;
990 case Lanczos2SharpFilter:
991 resize_filter->blur *= (MagickRealType) 0.9549963639785485;
1003 if ((resize_filter->filter == Gaussian) ||
1004 (resize_filter->window == Gaussian) ) {
1006 artifact=GetImageArtifact(image,
"filter:sigma");
1007 if (artifact != (
const char *) NULL)
1008 value=StringToDouble(artifact,(
char **) NULL);
1010 resize_filter->coefficient[0]=value;
1011 resize_filter->coefficient[1]=PerceptibleReciprocal(2.0*value*value);
1012 resize_filter->coefficient[2]=PerceptibleReciprocal(Magick2PI*value*value);
1015 resize_filter->support *= value/0.5;
1019 if ((resize_filter->filter == Kaiser) ||
1020 (resize_filter->window == Kaiser) ) {
1022 artifact=GetImageArtifact(image,
"filter:alpha");
1023 if (artifact != (
const char *) NULL)
1024 value=StringToDouble(artifact,(
char **) NULL);
1025 artifact=GetImageArtifact(image,
"filter:kaiser-beta");
1026 if (artifact != (
const char *) NULL)
1027 value=StringToDouble(artifact,(
char **) NULL);
1028 artifact=GetImageArtifact(image,
"filter:kaiser-alpha");
1029 if (artifact != (
const char *) NULL)
1030 value=(MagickRealType) (StringToDouble(artifact,(
char **) NULL)*MagickPI);
1032 resize_filter->coefficient[0]=value;
1033 resize_filter->coefficient[1]=PerceptibleReciprocal(I0(value));
1037 artifact=GetImageArtifact(image,
"filter:lobes");
1038 if (artifact != (
const char *) NULL)
1043 lobes=(ssize_t) StringToLong(artifact);
1046 resize_filter->support=(MagickRealType) lobes;
1049 if (resize_filter->filter == Jinc)
1051 if (resize_filter->support > 16)
1052 resize_filter->support=jinc_zeros[15];
1054 resize_filter->support=jinc_zeros[((long)resize_filter->support)-1];
1057 if (filter_type == LanczosRadiusFilter)
1059 resize_filter->blur *= floor(resize_filter->support)/
1060 resize_filter->support;
1064 artifact=GetImageArtifact(image,
"filter:blur");
1065 if (artifact != (
const char *) NULL)
1066 resize_filter->blur*=StringToDouble(artifact,(
char **) NULL);
1067 if (resize_filter->blur < MagickEpsilon)
1068 resize_filter->blur=(MagickRealType) MagickEpsilon;
1071 artifact=GetImageArtifact(image,
"filter:support");
1072 if (artifact != (
const char *) NULL)
1073 resize_filter->support=fabs(StringToDouble(artifact,(
char **) NULL));
1079 resize_filter->window_support=resize_filter->support;
1080 artifact=GetImageArtifact(image,
"filter:win-support");
1081 if (artifact != (
const char *) NULL)
1082 resize_filter->window_support=fabs(StringToDouble(artifact,(
char **) NULL));
1087 resize_filter->scale*=PerceptibleReciprocal(resize_filter->window_support);
1093 if ((resize_filter->filter == CubicBC) ||
1094 (resize_filter->window == CubicBC) )
1096 B=filters[filter_type].B;
1097 C=filters[filter_type].C;
1098 if (filters[window_type].function == CubicBC)
1100 B=filters[window_type].B;
1101 C=filters[window_type].C;
1103 artifact=GetImageArtifact(image,
"filter:b");
1104 if (artifact != (
const char *) NULL)
1106 B=StringToDouble(artifact,(
char **) NULL);
1108 artifact=GetImageArtifact(image,
"filter:c");
1109 if (artifact != (
const char *) NULL)
1110 C=StringToDouble(artifact,(
char **) NULL);
1114 artifact=GetImageArtifact(image,
"filter:c");
1115 if (artifact != (
const char *) NULL)
1117 C=StringToDouble(artifact,(
char **) NULL);
1123 const double twoB = B+B;
1124 resize_filter->coefficient[0]=1.0-(1.0/3.0)*B;
1125 resize_filter->coefficient[1]=-3.0+twoB+C;
1126 resize_filter->coefficient[2]=2.0-1.5*B-C;
1127 resize_filter->coefficient[3]=(4.0/3.0)*B+4.0*C;
1128 resize_filter->coefficient[4]=-8.0*C-twoB;
1129 resize_filter->coefficient[5]=B+5.0*C;
1130 resize_filter->coefficient[6]=(-1.0/6.0)*B-C;
1137 artifact=GetImageArtifact(image,
"filter:verbose");
1138 if (IsMagickTrue(artifact) != MagickFalse)
1139#if defined(MAGICKCORE_OPENMP_SUPPORT)
1153 if (resize_filter->filter == Box) filter_type=BoxFilter;
1154 if (resize_filter->filter == Sinc) filter_type=SincFilter;
1155 if (resize_filter->filter == SincFast) filter_type=SincFastFilter;
1156 if (resize_filter->filter == Jinc) filter_type=JincFilter;
1157 if (resize_filter->filter == CubicBC) filter_type=CubicFilter;
1158 if (resize_filter->window == Box) window_type=BoxFilter;
1159 if (resize_filter->window == Sinc) window_type=SincFilter;
1160 if (resize_filter->window == SincFast) window_type=SincFastFilter;
1161 if (resize_filter->window == Jinc) window_type=JincFilter;
1162 if (resize_filter->window == CubicBC) window_type=CubicFilter;
1166 support=GetResizeFilterSupport(resize_filter);
1167 (void) FormatLocaleFile(stdout,
"# Resampling Filter (for graphing)\n#\n");
1168 (void) FormatLocaleFile(stdout,
"# filter = %s\n",
1169 CommandOptionToMnemonic(MagickFilterOptions,filter_type));
1170 (void) FormatLocaleFile(stdout,
"# window = %s\n",
1171 CommandOptionToMnemonic(MagickFilterOptions,window_type));
1172 (void) FormatLocaleFile(stdout,
"# support = %.*g\n",GetMagickPrecision(),
1173 (
double) resize_filter->support);
1174 (void) FormatLocaleFile(stdout,
"# window-support = %.*g\n",
1175 GetMagickPrecision(),(
double) resize_filter->window_support);
1176 (void) FormatLocaleFile(stdout,
"# scale-blur = %.*g\n",
1177 GetMagickPrecision(),(
double) resize_filter->blur);
1178 if ((filter_type == GaussianFilter) || (window_type == GaussianFilter))
1179 (void) FormatLocaleFile(stdout,
"# gaussian-sigma = %.*g\n",
1180 GetMagickPrecision(), (
double)resize_filter->coefficient[0]);
1181 if ((filter_type == KaiserFilter) || (window_type == KaiserFilter))
1182 (void) FormatLocaleFile(stdout,
"# kaiser-beta = %.*g\n",
1183 GetMagickPrecision(),(
double)resize_filter->coefficient[0]);
1184 (void) FormatLocaleFile(stdout,
"# practical-support = %.*g\n",
1185 GetMagickPrecision(), (
double)support);
1186 if ((filter_type == CubicFilter) || (window_type == CubicFilter))
1187 (void) FormatLocaleFile(stdout,
"# B,C = %.*g,%.*g\n",
1188 GetMagickPrecision(),(
double)B,GetMagickPrecision(),(
double)C);
1189 (void) FormatLocaleFile(stdout,
"\n");
1193 for (x=0.0; x <= support; x+=0.01)
1194 (
void) FormatLocaleFile(stdout,
"%5.2lf\t%.*g\n",x,
1195 GetMagickPrecision(),(
double)
1196 GetResizeFilterWeight(resize_filter,x));
1198 (void) FormatLocaleFile(stdout,
"%5.2lf\t%.*g\n",support,
1199 GetMagickPrecision(),0.0);
1201 (void) DeleteImageArtifact((
Image *) image,
"filter:verbose");
1203 return(resize_filter);
1240MagickExport
Image *AdaptiveResizeImage(
const Image *image,
1241 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
1243 return(InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
1287static MagickRealType I0(MagickRealType x)
1303 for (i=2; t > MagickEpsilon; i++)
1306 t*=y/((MagickRealType) i*i);
1312static MagickRealType J1(MagickRealType x)
1324 0.581199354001606143928050809e+21,
1325 -0.6672106568924916298020941484e+20,
1326 0.2316433580634002297931815435e+19,
1327 -0.3588817569910106050743641413e+17,
1328 0.2908795263834775409737601689e+15,
1329 -0.1322983480332126453125473247e+13,
1330 0.3413234182301700539091292655e+10,
1331 -0.4695753530642995859767162166e+7,
1332 0.270112271089232341485679099e+4
1336 0.11623987080032122878585294e+22,
1337 0.1185770712190320999837113348e+20,
1338 0.6092061398917521746105196863e+17,
1339 0.2081661221307607351240184229e+15,
1340 0.5243710262167649715406728642e+12,
1341 0.1013863514358673989967045588e+10,
1342 0.1501793594998585505921097578e+7,
1343 0.1606931573481487801970916749e+4,
1349 for (i=7; i >= 0; i--)
1358static MagickRealType P1(MagickRealType x)
1370 0.352246649133679798341724373e+5,
1371 0.62758845247161281269005675e+5,
1372 0.313539631109159574238669888e+5,
1373 0.49854832060594338434500455e+4,
1374 0.2111529182853962382105718e+3,
1375 0.12571716929145341558495e+1
1379 0.352246649133679798068390431e+5,
1380 0.626943469593560511888833731e+5,
1381 0.312404063819041039923015703e+5,
1382 0.4930396490181088979386097e+4,
1383 0.2030775189134759322293574e+3,
1389 for (i=4; i >= 0; i--)
1391 p=p*(8.0/x)*(8.0/x)+Pone[i];
1392 q=q*(8.0/x)*(8.0/x)+Qone[i];
1398static MagickRealType Q1(MagickRealType x)
1410 0.3511751914303552822533318e+3,
1411 0.7210391804904475039280863e+3,
1412 0.4259873011654442389886993e+3,
1413 0.831898957673850827325226e+2,
1414 0.45681716295512267064405e+1,
1415 0.3532840052740123642735e-1
1419 0.74917374171809127714519505e+4,
1420 0.154141773392650970499848051e+5,
1421 0.91522317015169922705904727e+4,
1422 0.18111867005523513506724158e+4,
1423 0.1038187585462133728776636e+3,
1429 for (i=4; i >= 0; i--)
1431 p=p*(8.0/x)*(8.0/x)+Pone[i];
1432 q=q*(8.0/x)*(8.0/x)+Qone[i];
1437static MagickRealType BesselOrderOne(MagickRealType x)
1450 q=sqrt((
double) (2.0/(MagickPI*x)))*(P1(x)*(1.0/sqrt(2.0)*(sin((
double) x)-
1451 cos((
double) x)))-8.0/x*Q1(x)*(-1.0/sqrt(2.0)*(sin((
double) x)+
1483 assert(resize_filter->signature == MagickCoreSignature);
1484 resize_filter->signature=(~MagickCoreSignature);
1485 resize_filter=(
ResizeFilter *) RelinquishMagickMemory(resize_filter);
1486 return(resize_filter);
1513MagickExport MagickRealType *GetResizeFilterCoefficient(
1517 assert(resize_filter->signature == MagickCoreSignature);
1518 return((MagickRealType *) resize_filter->coefficient);
1521MagickExport MagickRealType GetResizeFilterBlur(
1525 assert(resize_filter->signature == MagickCoreSignature);
1526 return(resize_filter->blur);
1529MagickExport MagickRealType GetResizeFilterScale(
1533 assert(resize_filter->signature == MagickCoreSignature);
1534 return(resize_filter->scale);
1537MagickExport MagickRealType GetResizeFilterWindowSupport(
1541 assert(resize_filter->signature == MagickCoreSignature);
1542 return(resize_filter->window_support);
1545MagickExport ResizeWeightingFunctionType GetResizeFilterWeightingType(
1549 assert(resize_filter->signature == MagickCoreSignature);
1550 return(resize_filter->filterWeightingType);
1553MagickExport ResizeWeightingFunctionType GetResizeFilterWindowWeightingType(
1557 assert(resize_filter->signature == MagickCoreSignature);
1558 return(resize_filter->windowWeightingType);
1561MagickExport MagickRealType GetResizeFilterSupport(
1565 assert(resize_filter->signature == MagickCoreSignature);
1566 return(resize_filter->support*resize_filter->blur);
1596MagickExport MagickRealType GetResizeFilterWeight(
1597 const ResizeFilter *resize_filter,
const MagickRealType x)
1608 assert(resize_filter->signature == MagickCoreSignature);
1609 x_blur=fabs((
double) x)*PerceptibleReciprocal(resize_filter->blur);
1610 if ((resize_filter->window_support < MagickEpsilon) ||
1611 (resize_filter->window == Box))
1615 scale=resize_filter->scale;
1616 scale=resize_filter->window(x_blur*scale,resize_filter);
1618 weight=scale*resize_filter->filter(x_blur,resize_filter);
1655MagickExport
Image *InterpolativeResizeImage(
const Image *image,
1656 const size_t columns,
const size_t rows,
const InterpolatePixelMethod method,
1659#define InterpolativeResizeImageTag "Resize/Image"
1683 assert(image != (
const Image *) NULL);
1684 assert(image->signature == MagickCoreSignature);
1686 assert(exception->signature == MagickCoreSignature);
1687 if (IsEventLogging() != MagickFalse)
1688 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1689 if ((columns == 0) || (rows == 0))
1690 return((
Image *) NULL);
1691 if ((columns == image->columns) && (rows == image->rows))
1692 return(CloneImage(image,0,0,MagickTrue,exception));
1693 resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
1694 if (resize_image == (
Image *) NULL)
1695 return((
Image *) NULL);
1696 if (SetImageStorageClass(resize_image,DirectClass) == MagickFalse)
1698 InheritException(exception,&resize_image->exception);
1699 resize_image=DestroyImage(resize_image);
1700 return((
Image *) NULL);
1704 image_view=AcquireVirtualCacheView(image,exception);
1705 resize_view=AcquireAuthenticCacheView(resize_image,exception);
1706 scale.x=(double) image->columns/resize_image->columns;
1707 scale.y=(double) image->rows/resize_image->rows;
1708#if defined(MAGICKCORE_OPENMP_SUPPORT)
1709 #pragma omp parallel for schedule(static) shared(progress,status) \
1710 magick_number_threads(image,resize_image,resize_image->rows,1)
1712 for (y=0; y < (ssize_t) resize_image->rows; y++)
1721 *magick_restrict resize_indexes;
1729 if (status == MagickFalse)
1731 q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
1735 resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
1736 GetMagickPixelPacket(image,&pixel);
1737 offset.y=((MagickRealType) y+0.5)*scale.y-0.5;
1738 for (x=0; x < (ssize_t) resize_image->columns; x++)
1740 offset.x=((MagickRealType) x+0.5)*scale.x-0.5;
1741 status=InterpolateMagickPixelPacket(image,image_view,method,offset.x,
1742 offset.y,&pixel,exception);
1743 if (status == MagickFalse)
1745 SetPixelPacket(resize_image,&pixel,q,resize_indexes+x);
1748 if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
1750 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1755#if defined(MAGICKCORE_OPENMP_SUPPORT)
1759 proceed=SetImageProgress(image,InterpolativeResizeImageTag,progress,
1761 if (proceed == MagickFalse)
1765 resize_view=DestroyCacheView(resize_view);
1766 image_view=DestroyCacheView(image_view);
1767 if (status == MagickFalse)
1768 resize_image=DestroyImage(resize_image);
1769 return(resize_image);
1771#if defined(MAGICKCORE_LQR_DELEGATE)
1807MagickExport
Image *LiquidRescaleImage(
const Image *image,
const size_t columns,
1808 const size_t rows,
const double delta_x,
const double rigidity,
1811#define LiquidRescaleImageTag "Rescale/Image"
1850 assert(image != (
const Image *) NULL);
1851 assert(image->signature == MagickCoreSignature);
1853 assert(exception->signature == MagickCoreSignature);
1854 if (IsEventLogging() != MagickFalse)
1855 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1856 if ((columns == 0) || (rows == 0))
1857 return((
Image *) NULL);
1858 if ((columns == image->columns) && (rows == image->rows))
1859 return(CloneImage(image,0,0,MagickTrue,exception));
1860 if ((columns <= 2) || (rows <= 2))
1861 return(ResizeImage(image,columns,rows,image->filter,image->blur,exception));
1863 if (image->matte != MagickFalse)
1865 if (image->colorspace == CMYKColorspace)
1868 if (image->matte != MagickFalse)
1871 pixel_info=AcquireVirtualMemory(image->columns,image->rows*strlen(map)*
1874 return((
Image *) NULL);
1875 pixels=(
unsigned char *) GetVirtualMemoryBlob(pixel_info);
1876 status=ExportImagePixels(image,0,0,image->columns,image->rows,map,CharPixel,
1878 if (status == MagickFalse)
1880 pixel_info=RelinquishVirtualMemory(pixel_info);
1881 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1883 carver=lqr_carver_new(pixels,(
int) image->columns,(
int) image->rows,
1885 if (carver == (LqrCarver *) NULL)
1887 pixel_info=RelinquishVirtualMemory(pixel_info);
1888 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1890 lqr_carver_set_preserve_input_image(carver);
1891 lqr_status=lqr_carver_init(carver,(
int) delta_x,rigidity);
1892 lqr_status=lqr_carver_resize(carver,(
int) columns,(
int) rows);
1894 rescale_image=CloneImage(image,lqr_carver_get_width(carver),
1895 lqr_carver_get_height(carver),MagickTrue,exception);
1896 if (rescale_image == (
Image *) NULL)
1898 pixel_info=RelinquishVirtualMemory(pixel_info);
1899 return((
Image *) NULL);
1901 if (SetImageStorageClass(rescale_image,DirectClass) == MagickFalse)
1903 InheritException(exception,&rescale_image->exception);
1904 rescale_image=DestroyImage(rescale_image);
1905 return((
Image *) NULL);
1907 GetMagickPixelPacket(rescale_image,&pixel);
1908 (void) lqr_carver_scan_reset(carver);
1909 rescale_view=AcquireAuthenticCacheView(rescale_image,exception);
1910 while (lqr_carver_scan(carver,&x,&y,&packet) != 0)
1913 *magick_restrict rescale_indexes;
1918 q=QueueCacheViewAuthenticPixels(rescale_view,x,y,1,1,exception);
1921 rescale_indexes=GetCacheViewAuthenticIndexQueue(rescale_view);
1922 pixel.red=(MagickRealType) QuantumRange*(packet[0]/255.0);
1923 pixel.green=(MagickRealType) QuantumRange*(packet[1]/255.0);
1924 pixel.blue=(MagickRealType) QuantumRange*(packet[2]/255.0);
1925 if (image->colorspace != CMYKColorspace)
1927 if (image->matte != MagickFalse)
1928 pixel.opacity=(MagickRealType) QuantumRange-(MagickRealType)
1929 QuantumRange*(packet[3]/255.0);
1933 pixel.index=(MagickRealType) QuantumRange*(packet[3]/255.0);
1934 if (image->matte != MagickFalse)
1935 pixel.opacity=(MagickRealType) QuantumRange-(MagickRealType)
1936 QuantumRange*(packet[4]/255.0);
1938 SetPixelPacket(rescale_image,&pixel,q,rescale_indexes);
1939 if (SyncCacheViewAuthenticPixels(rescale_view,exception) == MagickFalse)
1942 rescale_view=DestroyCacheView(rescale_view);
1946 pixel_info=RelinquishVirtualMemory(pixel_info);
1947 lqr_carver_destroy(carver);
1948 return(rescale_image);
1951MagickExport
Image *LiquidRescaleImage(
const Image *image,
1952 const size_t magick_unused(columns),
const size_t magick_unused(rows),
1953 const double magick_unused(delta_x),
const double magick_unused(rigidity),
1956 assert(image != (
const Image *) NULL);
1957 assert(image->signature == MagickCoreSignature);
1959 assert(exception->signature == MagickCoreSignature);
1960 if (IsEventLogging() != MagickFalse)
1961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1962 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
1963 "DelegateLibrarySupportNotBuiltIn",
"`%s' (LQR)",image->filename);
1964 return((
Image *) NULL);
1995#define MagnifyImageTag "Magnify/Image"
2016 assert(image != (
const Image *) NULL);
2017 assert(image->signature == MagickCoreSignature);
2019 assert(exception->signature == MagickCoreSignature);
2020 if (IsEventLogging() != MagickFalse)
2021 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2022 magnify_image=CloneImage(image,2*image->columns,2*image->rows,MagickTrue,
2024 if (magnify_image == (
Image *) NULL)
2025 return((
Image *) NULL);
2031 image_view=AcquireVirtualCacheView(image,exception);
2032 magnify_view=AcquireAuthenticCacheView(magnify_image,exception);
2033#if defined(MAGICKCORE_OPENMP_SUPPORT)
2034 #pragma omp parallel for schedule(static) shared(progress,status) \
2035 magick_number_threads(image,magnify_image,image->rows,1)
2037 for (y=0; y < (ssize_t) image->rows; y++)
2040 *magick_restrict magnify_indexes;
2048 if (status == MagickFalse)
2050 q=QueueCacheViewAuthenticPixels(magnify_view,0,2*y,magnify_image->columns,2,
2057 magnify_indexes=GetCacheViewAuthenticIndexQueue(magnify_view);
2058 for (x=0; x < (ssize_t) image->columns; x++)
2061 *magick_restrict indexes;
2078 p=GetCacheViewVirtualPixels(image_view,x-1,y-1,3,3,exception);
2084 indexes=GetCacheViewVirtualIndexQueue(image_view);
2085 for (i=0; i < 9; i++)
2086 intensity[i]=GetPixelIntensity(image,p+i);
2088 if ((fabs((
double) (intensity[1]-intensity[7])) < MagickEpsilon) ||
2089 (fabs((
double) (intensity[3]-intensity[5])) < MagickEpsilon))
2097 r+=(ptrdiff_t) (magnify_image->columns-1);
2107 if (fabs((
double) (intensity[1]-intensity[3])) < MagickEpsilon)
2112 if (fabs((
double) (intensity[1]-intensity[5])) < MagickEpsilon)
2116 r+=(ptrdiff_t) (magnify_image->columns-1);
2117 if (fabs((
double) (intensity[3]-intensity[7])) < MagickEpsilon)
2122 if (fabs((
double) (intensity[5]-intensity[7])) < MagickEpsilon)
2127 if (indexes != (
const IndexPacket *) NULL)
2136 if ((fabs((
double) (intensity[1]-intensity[7])) < MagickEpsilon) ||
2137 (fabs((
double) (intensity[3]-intensity[5])) < MagickEpsilon))
2145 r+=(ptrdiff_t) (magnify_image->columns-1);
2155 if (fabs((
double) (intensity[1]-intensity[3])) < MagickEpsilon)
2160 if (fabs((
double) (intensity[1]-intensity[5])) < MagickEpsilon)
2164 r+=(ptrdiff_t) (magnify_image->columns-1);
2165 if (fabs((
double) (intensity[3]-intensity[7])) < MagickEpsilon)
2170 if (fabs((
double) (intensity[5]-intensity[7])) < MagickEpsilon)
2179 if (SyncCacheViewAuthenticPixels(magnify_view,exception) == MagickFalse)
2181 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2186#if defined(MAGICKCORE_OPENMP_SUPPORT)
2190 proceed=SetImageProgress(image,MagnifyImageTag,progress,image->rows);
2191 if (proceed == MagickFalse)
2195 magnify_view=DestroyCacheView(magnify_view);
2196 image_view=DestroyCacheView(image_view);
2197 if (status == MagickFalse)
2198 magnify_image=DestroyImage(magnify_image);
2199 return(magnify_image);
2232 assert(image != (
Image *) NULL);
2233 assert(image->signature == MagickCoreSignature);
2235 assert(exception->signature == MagickCoreSignature);
2236 if (IsEventLogging() != MagickFalse)
2237 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2238 minify_image=ResizeImage(image,image->columns/2,image->rows/2,SplineFilter,
2240 return(minify_image);
2277MagickExport
Image *ResampleImage(
const Image *image,
const double x_resolution,
2278 const double y_resolution,
const FilterTypes filter,
const double blur,
2281#define ResampleImageTag "Resample/Image"
2293 assert(image != (
const Image *) NULL);
2294 assert(image->signature == MagickCoreSignature);
2296 assert(exception->signature == MagickCoreSignature);
2297 if (IsEventLogging() != MagickFalse)
2298 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2299 width=(size_t) (x_resolution*image->columns/(image->x_resolution == 0.0 ?
2300 DefaultResolution : image->x_resolution)+0.5);
2301 height=(size_t) (y_resolution*image->rows/(image->y_resolution == 0.0 ?
2302 DefaultResolution : image->y_resolution)+0.5);
2303 resample_image=ResizeImage(image,width,height,filter,blur,exception);
2304 if (resample_image != (
Image *) NULL)
2306 resample_image->x_resolution=x_resolution;
2307 resample_image->y_resolution=y_resolution;
2309 return(resample_image);
2371 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
2376 return(contribution);
2390 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
2392 sizeof(*contribution));
2395 (void) memset(contribution,0,number_threads*
sizeof(*contribution));
2396 for (i=0; i < (ssize_t) number_threads; i++)
2399 AcquireAlignedMemory(count,
sizeof(**contribution)));
2401 return(DestroyContributionTLS(contribution));
2403 return(contribution);
2406static MagickBooleanType HorizontalFilter(
2408 const Image *magick_restrict image,
Image *magick_restrict resize_image,
2409 const MagickRealType x_factor,
const MagickSizeType span,
2410 MagickOffsetType *magick_restrict offset,
ExceptionInfo *exception)
2412#define ResizeImageTag "Resize/Image"
2422 **magick_restrict contributions;
2440 scale=MagickMax(1.0/x_factor+MagickEpsilon,1.0);
2441 support=scale*GetResizeFilterSupport(resize_filter);
2442 storage_class=support > 0.5 ? DirectClass : image->storage_class;
2443 if (SetImageStorageClass(resize_image,storage_class) == MagickFalse)
2445 InheritException(exception,&resize_image->exception);
2446 return(MagickFalse);
2454 support=(MagickRealType) 0.5;
2457 contributions=AcquireContributionTLS((
size_t) (2.0*support+3.0));
2460 (void) ThrowMagickException(exception,GetMagickModule(),
2461 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",image->filename);
2462 return(MagickFalse);
2465 scale=PerceptibleReciprocal(scale);
2466 (void) memset(&zero,0,
sizeof(zero));
2467 image_view=AcquireVirtualCacheView(image,exception);
2468 resize_view=AcquireAuthenticCacheView(resize_image,exception);
2469#if defined(MAGICKCORE_OPENMP_SUPPORT)
2470 #pragma omp parallel for schedule(static) shared(status,offset) \
2471 magick_number_threads(image,resize_image,resize_image->columns,1)
2473 for (x=0; x < (ssize_t) resize_image->columns; x++)
2476 id = GetOpenMPThreadId();
2483 *magick_restrict indexes;
2489 *magick_restrict contribution;
2492 *magick_restrict resize_indexes;
2505 if (status == MagickFalse)
2507 bisect=(MagickRealType) (x+0.5)/x_factor+MagickEpsilon;
2508 start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
2509 stop=(ssize_t) MagickMin(bisect+support+0.5,(
double) image->columns);
2511 contribution=contributions[id];
2512 for (n=0; n < (stop-start); n++)
2514 contribution[n].pixel=start+n;
2515 contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
2516 ((MagickRealType) (start+n)-bisect+0.5));
2517 density+=contribution[n].weight;
2521 if ((density != 0.0) && (density != 1.0))
2529 density=PerceptibleReciprocal(density);
2530 for (i=0; i < n; i++)
2531 contribution[i].weight*=density;
2533 p=GetCacheViewVirtualPixels(image_view,contribution[0].pixel,0,(
size_t)
2534 (contribution[n-1].pixel-contribution[0].pixel+1),image->rows,exception);
2535 q=QueueCacheViewAuthenticPixels(resize_view,x,0,1,resize_image->rows,
2542 indexes=GetCacheViewVirtualIndexQueue(image_view);
2543 resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
2544 for (y=0; y < (ssize_t) resize_image->rows; y++)
2559 if (image->matte == MagickFalse)
2561 for (i=0; i < n; i++)
2563 j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
2564 (contribution[i].pixel-contribution[0].pixel);
2565 alpha=contribution[i].weight;
2566 pixel.red+=alpha*(MagickRealType) GetPixelRed(p+j);
2567 pixel.green+=alpha*(MagickRealType) GetPixelGreen(p+j);
2568 pixel.blue+=alpha*(MagickRealType) GetPixelBlue(p+j);
2569 pixel.opacity+=alpha*(MagickRealType) GetPixelOpacity(p+j);
2571 SetPixelRed(q,ClampToQuantum(pixel.red));
2572 SetPixelGreen(q,ClampToQuantum(pixel.green));
2573 SetPixelBlue(q,ClampToQuantum(pixel.blue));
2574 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
2575 if ((image->colorspace == CMYKColorspace) &&
2576 (resize_image->colorspace == CMYKColorspace))
2578 for (i=0; i < n; i++)
2580 j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
2581 (contribution[i].pixel-contribution[0].pixel);
2582 alpha=contribution[i].weight;
2583 pixel.index+=alpha*(MagickRealType) GetPixelIndex(indexes+j);
2585 SetPixelIndex(resize_indexes+y,ClampToQuantum(pixel.index));
2594 for (i=0; i < n; i++)
2596 j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
2597 (contribution[i].pixel-contribution[0].pixel);
2598 alpha=contribution[i].weight*QuantumScale*(MagickRealType)
2600 pixel.red+=alpha*(MagickRealType) GetPixelRed(p+j);
2601 pixel.green+=alpha*(MagickRealType) GetPixelGreen(p+j);
2602 pixel.blue+=alpha*(MagickRealType) GetPixelBlue(p+j);
2603 pixel.opacity+=contribution[i].weight*(MagickRealType)
2604 GetPixelOpacity(p+j);
2607 gamma=PerceptibleReciprocal(gamma);
2608 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
2609 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) pixel.green));
2610 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) pixel.blue));
2611 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
2612 if ((image->colorspace == CMYKColorspace) &&
2613 (resize_image->colorspace == CMYKColorspace))
2615 for (i=0; i < n; i++)
2617 j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
2618 (contribution[i].pixel-contribution[0].pixel);
2619 alpha=contribution[i].weight*QuantumScale*(MagickRealType)
2621 pixel.index+=alpha*(MagickRealType) GetPixelIndex(indexes+j);
2623 SetPixelIndex(resize_indexes+y,ClampToQuantum(gamma*pixel.index));
2626 if ((resize_image->storage_class == PseudoClass) &&
2627 (image->storage_class == PseudoClass))
2629 i=(ssize_t) (MagickMin(MagickMax(bisect,(
double) start),(
double) stop-
2631 j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
2632 (contribution[i-start].pixel-contribution[0].pixel);
2633 SetPixelIndex(resize_indexes+y,GetPixelIndex(indexes+j));
2637 if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
2639 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2644#if defined(MAGICKCORE_OPENMP_SUPPORT)
2648 proceed=SetImageProgress(image,ResizeImageTag,*offset,span);
2649 if (proceed == MagickFalse)
2653 resize_view=DestroyCacheView(resize_view);
2654 image_view=DestroyCacheView(image_view);
2655 contributions=DestroyContributionTLS(contributions);
2659static MagickBooleanType VerticalFilter(
2661 const Image *magick_restrict image,
Image *magick_restrict resize_image,
2662 const MagickRealType y_factor,
const MagickSizeType span,
2663 MagickOffsetType *magick_restrict offset,
ExceptionInfo *exception)
2673 **magick_restrict contributions;
2691 scale=MagickMax(1.0/y_factor+MagickEpsilon,1.0);
2692 support=scale*GetResizeFilterSupport(resize_filter);
2693 storage_class=support > 0.5 ? DirectClass : image->storage_class;
2694 if (SetImageStorageClass(resize_image,storage_class) == MagickFalse)
2696 InheritException(exception,&resize_image->exception);
2697 return(MagickFalse);
2705 support=(MagickRealType) 0.5;
2708 contributions=AcquireContributionTLS((
size_t) (2.0*support+3.0));
2711 (void) ThrowMagickException(exception,GetMagickModule(),
2712 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",image->filename);
2713 return(MagickFalse);
2716 scale=PerceptibleReciprocal(scale);
2717 (void) memset(&zero,0,
sizeof(zero));
2718 image_view=AcquireVirtualCacheView(image,exception);
2719 resize_view=AcquireAuthenticCacheView(resize_image,exception);
2720#if defined(MAGICKCORE_OPENMP_SUPPORT)
2721 #pragma omp parallel for schedule(static) shared(status,offset) \
2722 magick_number_threads(image,resize_image,resize_image->rows,1)
2724 for (y=0; y < (ssize_t) resize_image->rows; y++)
2727 id = GetOpenMPThreadId();
2734 *magick_restrict indexes;
2740 *magick_restrict contribution;
2743 *magick_restrict resize_indexes;
2756 if (status == MagickFalse)
2758 bisect=(MagickRealType) (y+0.5)/y_factor+MagickEpsilon;
2759 start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
2760 stop=(ssize_t) MagickMin(bisect+support+0.5,(
double) image->rows);
2762 contribution=contributions[id];
2763 for (n=0; n < (stop-start); n++)
2765 contribution[n].pixel=start+n;
2766 contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
2767 ((MagickRealType) (start+n)-bisect+0.5));
2768 density+=contribution[n].weight;
2772 if ((density != 0.0) && (density != 1.0))
2780 density=PerceptibleReciprocal(density);
2781 for (i=0; i < n; i++)
2782 contribution[i].weight*=density;
2784 p=GetCacheViewVirtualPixels(image_view,0,contribution[0].pixel,
2785 image->columns,(
size_t) (contribution[n-1].pixel-contribution[0].pixel+1),
2787 q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
2794 indexes=GetCacheViewVirtualIndexQueue(image_view);
2795 resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
2796 for (x=0; x < (ssize_t) resize_image->columns; x++)
2811 if (image->matte == MagickFalse)
2813 for (i=0; i < n; i++)
2815 j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
2817 alpha=contribution[i].weight;
2818 pixel.red+=alpha*(MagickRealType) GetPixelRed(p+j);
2819 pixel.green+=alpha*(MagickRealType) GetPixelGreen(p+j);
2820 pixel.blue+=alpha*(MagickRealType) GetPixelBlue(p+j);
2821 pixel.opacity+=alpha*(MagickRealType) GetPixelOpacity(p+j);
2823 SetPixelRed(q,ClampToQuantum(pixel.red));
2824 SetPixelGreen(q,ClampToQuantum(pixel.green));
2825 SetPixelBlue(q,ClampToQuantum(pixel.blue));
2826 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
2827 if ((image->colorspace == CMYKColorspace) &&
2828 (resize_image->colorspace == CMYKColorspace))
2830 for (i=0; i < n; i++)
2832 j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
2834 alpha=contribution[i].weight;
2835 pixel.index+=alpha*(MagickRealType) GetPixelIndex(indexes+j);
2837 SetPixelIndex(resize_indexes+x,ClampToQuantum(pixel.index));
2846 for (i=0; i < n; i++)
2848 j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
2850 alpha=contribution[i].weight*QuantumScale*(MagickRealType)
2852 pixel.red+=alpha*(MagickRealType) GetPixelRed(p+j);
2853 pixel.green+=alpha*(MagickRealType) GetPixelGreen(p+j);
2854 pixel.blue+=alpha*(MagickRealType) GetPixelBlue(p+j);
2855 pixel.opacity+=contribution[i].weight*(MagickRealType)
2856 GetPixelOpacity(p+j);
2859 gamma=PerceptibleReciprocal(gamma);
2860 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
2861 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) pixel.green));
2862 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) pixel.blue));
2863 SetPixelOpacity(q,ClampToQuantum((MagickRealType) pixel.opacity));
2864 if ((image->colorspace == CMYKColorspace) &&
2865 (resize_image->colorspace == CMYKColorspace))
2867 for (i=0; i < n; i++)
2869 j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
2871 alpha=contribution[i].weight*QuantumScale*(MagickRealType)
2873 pixel.index+=alpha*(MagickRealType) GetPixelIndex(indexes+j);
2875 SetPixelIndex(resize_indexes+x,ClampToQuantum(gamma*
2876 (MagickRealType) pixel.index));
2879 if ((resize_image->storage_class == PseudoClass) &&
2880 (image->storage_class == PseudoClass))
2882 i=(ssize_t) (MagickMin(MagickMax(bisect,(
double) start),(
double) stop-
2884 j=(ssize_t) ((contribution[i-start].pixel-contribution[0].pixel)*
2886 SetPixelIndex(resize_indexes+x,GetPixelIndex(indexes+j));
2890 if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
2892 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2897#if defined(MAGICKCORE_OPENMP_SUPPORT)
2901 proceed=SetImageProgress(image,ResizeImageTag,*offset,span);
2902 if (proceed == MagickFalse)
2906 resize_view=DestroyCacheView(resize_view);
2907 image_view=DestroyCacheView(image_view);
2908 contributions=DestroyContributionTLS(contributions);
2912MagickExport
Image *ResizeImage(
const Image *image,
const size_t columns,
2913 const size_t rows,
const FilterTypes filter,
const double blur,
2942 assert(image != (
Image *) NULL);
2943 assert(image->signature == MagickCoreSignature);
2945 assert(exception->signature == MagickCoreSignature);
2946 if (IsEventLogging() != MagickFalse)
2947 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2948 if ((columns == 0) || (rows == 0))
2949 ThrowImageException(ImageError,
"NegativeOrZeroImageSize");
2950 if ((columns == image->columns) && (rows == image->rows) &&
2951 (filter == UndefinedFilter) && (blur == 1.0))
2952 return(CloneImage(image,0,0,MagickTrue,exception));
2957 x_factor=(MagickRealType) (columns*
2958 PerceptibleReciprocal((
double) image->columns));
2959 y_factor=(MagickRealType) (rows*
2960 PerceptibleReciprocal((
double) image->rows));
2961 filter_type=LanczosFilter;
2962 if (filter != UndefinedFilter)
2965 if ((x_factor == 1.0) && (y_factor == 1.0))
2966 filter_type=PointFilter;
2968 if ((image->storage_class == PseudoClass) ||
2969 (image->matte != MagickFalse) || ((x_factor*y_factor) > 1.0))
2970 filter_type=MitchellFilter;
2971 resize_filter=AcquireResizeFilter(image,filter_type,blur,MagickFalse,
2973#if defined(MAGICKCORE_OPENCL_SUPPORT)
2974 resize_image=AccelerateResizeImage(image,columns,rows,resize_filter,
2976 if (resize_image != NULL)
2978 resize_filter=DestroyResizeFilter(resize_filter);
2979 return(resize_image);
2982 resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
2983 if (resize_image == (
Image *) NULL)
2985 resize_filter=DestroyResizeFilter(resize_filter);
2986 return(resize_image);
2988 if (x_factor > y_factor)
2989 filter_image=CloneImage(image,columns,image->rows,MagickTrue,exception);
2991 filter_image=CloneImage(image,image->columns,rows,MagickTrue,exception);
2992 if (filter_image == (
Image *) NULL)
2994 resize_filter=DestroyResizeFilter(resize_filter);
2995 return(DestroyImage(resize_image));
3001 if (x_factor > y_factor)
3003 span=(MagickSizeType) (filter_image->columns+rows);
3004 status=HorizontalFilter(resize_filter,image,filter_image,x_factor,span,
3006 status&=VerticalFilter(resize_filter,filter_image,resize_image,y_factor,
3007 span,&offset,exception);
3011 span=(MagickSizeType) (filter_image->rows+columns);
3012 status=VerticalFilter(resize_filter,image,filter_image,y_factor,span,
3014 status&=HorizontalFilter(resize_filter,filter_image,resize_image,x_factor,
3015 span,&offset,exception);
3020 filter_image=DestroyImage(filter_image);
3021 resize_filter=DestroyResizeFilter(resize_filter);
3022 if (status == MagickFalse)
3024 resize_image=DestroyImage(resize_image);
3025 return((
Image *) NULL);
3027 resize_image->type=image->type;
3028 return(resize_image);
3062MagickExport
Image *SampleImage(
const Image *image,
const size_t columns,
3065#define SampleImageTag "Sample/Image"
3093 assert(image != (
const Image *) NULL);
3094 assert(image->signature == MagickCoreSignature);
3096 assert(exception->signature == MagickCoreSignature);
3097 if (IsEventLogging() != MagickFalse)
3098 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3099 if ((columns == 0) || (rows == 0))
3100 ThrowImageException(ImageError,
"NegativeOrZeroImageSize");
3101 if ((columns == image->columns) && (rows == image->rows))
3102 return(CloneImage(image,0,0,MagickTrue,exception));
3103 sample_image=CloneImage(image,columns,rows,MagickTrue,exception);
3104 if (sample_image == (
Image *) NULL)
3105 return((
Image *) NULL);
3110 sample_offset.x=sample_offset.y=0.5-MagickEpsilon;
3115 value=GetImageArtifact(image,
"sample:offset");
3116 if (value != (
char *) NULL)
3123 (void) ParseGeometry(value,&geometry_info);
3124 flags=ParseGeometry(value,&geometry_info);
3125 sample_offset.x=sample_offset.y=geometry_info.rho/100.0-MagickEpsilon;
3126 if ((flags & SigmaValue) != 0)
3127 sample_offset.y=geometry_info.sigma/100.0-MagickEpsilon;
3133 x_offset=(ssize_t *) AcquireQuantumMemory((
size_t) sample_image->columns,
3135 if (x_offset == (ssize_t *) NULL)
3137 sample_image=DestroyImage(sample_image);
3138 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3140 for (x=0; x < (ssize_t) sample_image->columns; x++)
3141 x_offset[x]=(ssize_t) ((((double) x+sample_offset.x)*image->columns)/
3142 sample_image->columns);
3148 image_view=AcquireVirtualCacheView(image,exception);
3149 sample_view=AcquireAuthenticCacheView(sample_image,exception);
3150#if defined(MAGICKCORE_OPENMP_SUPPORT)
3151 #pragma omp parallel for schedule(static) shared(status) \
3152 magick_number_threads(image,sample_image,sample_image->rows,2)
3154 for (y=0; y < (ssize_t) sample_image->rows; y++)
3157 *magick_restrict indexes;
3163 *magick_restrict sample_indexes;
3174 if (status == MagickFalse)
3176 y_offset=(ssize_t) ((((
double) y+sample_offset.y)*image->rows)/
3177 sample_image->rows);
3178 p=GetCacheViewVirtualPixels(image_view,0,y_offset,image->columns,1,
3180 q=QueueCacheViewAuthenticPixels(sample_view,0,y,sample_image->columns,1,
3187 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3188 sample_indexes=GetCacheViewAuthenticIndexQueue(sample_view);
3192 for (x=0; x < (ssize_t) sample_image->columns; x++)
3193 *q++=p[x_offset[x]];
3194 if ((image->storage_class == PseudoClass) ||
3195 (image->colorspace == CMYKColorspace))
3196 for (x=0; x < (ssize_t) sample_image->columns; x++)
3197 SetPixelIndex(sample_indexes+x,GetPixelIndex(indexes+x_offset[x]));
3198 if (SyncCacheViewAuthenticPixels(sample_view,exception) == MagickFalse)
3200 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3205#if defined(MAGICKCORE_OPENMP_SUPPORT)
3209 proceed=SetImageProgress(image,SampleImageTag,progress,image->rows);
3210 if (proceed == MagickFalse)
3214 image_view=DestroyCacheView(image_view);
3215 sample_view=DestroyCacheView(sample_view);
3216 x_offset=(ssize_t *) RelinquishMagickMemory(x_offset);
3217 sample_image->type=image->type;
3218 if (status == MagickFalse)
3219 sample_image=DestroyImage(sample_image);
3220 return(sample_image);
3252MagickExport
Image *ScaleImage(
const Image *image,
const size_t columns,
3255#define ScaleImageTag "Scale/Image"
3295 assert(image != (
const Image *) NULL);
3296 assert(image->signature == MagickCoreSignature);
3298 assert(exception->signature == MagickCoreSignature);
3299 if (IsEventLogging() != MagickFalse)
3300 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3301 if ((columns == 0) || (rows == 0))
3302 return((
Image *) NULL);
3303 if ((columns == image->columns) && (rows == image->rows))
3304 return(CloneImage(image,0,0,MagickTrue,exception));
3305 scale_image=CloneImage(image,columns,rows,MagickTrue,exception);
3306 if (scale_image == (
Image *) NULL)
3307 return((
Image *) NULL);
3308 if (SetImageStorageClass(scale_image,DirectClass) == MagickFalse)
3310 InheritException(exception,&scale_image->exception);
3311 scale_image=DestroyImage(scale_image);
3312 return((
Image *) NULL);
3320 if (image->rows != scale_image->rows)
3324 scale_image->columns,
sizeof(*scale_scanline));
3332 if ((image->rows != scale_image->rows) &&
3342 scale_image=DestroyImage(scale_image);
3343 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3349 next_row=MagickTrue;
3351 scale.y=(double) scale_image->rows/(
double) image->rows;
3352 (void) memset(y_vector,0,(
size_t) image->columns*
3354 GetMagickPixelPacket(image,&pixel);
3355 (void) memset(&zero,0,
sizeof(zero));
3358 image_view=AcquireVirtualCacheView(image,exception);
3359 scale_view=AcquireAuthenticCacheView(scale_image,exception);
3360 for (y=0; y < (ssize_t) scale_image->rows; y++)
3363 *magick_restrict indexes;
3369 *magick_restrict scale_indexes;
3381 if (status == MagickFalse)
3383 q=QueueCacheViewAuthenticPixels(scale_view,0,y,scale_image->columns,1,
3391 scale_indexes=GetCacheViewAuthenticIndexQueue(scale_view);
3392 if (scale_image->rows == image->rows)
3397 p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
3404 indexes=GetCacheViewVirtualIndexQueue(image_view);
3405 for (x=0; x < (ssize_t) image->columns; x++)
3407 if (image->matte != MagickFalse)
3408 alpha=QuantumScale*GetPixelAlpha(p);
3409 x_vector[x].red=alpha*(MagickRealType) GetPixelRed(p);
3410 x_vector[x].green=alpha*(MagickRealType) GetPixelGreen(p);
3411 x_vector[x].blue=alpha*(MagickRealType) GetPixelBlue(p);
3412 if (image->matte != MagickFalse)
3413 x_vector[x].opacity=(MagickRealType) GetPixelOpacity(p);
3414 if (indexes != (IndexPacket *) NULL)
3415 x_vector[x].index=alpha*(MagickRealType) GetPixelIndex(indexes+x);
3424 while (scale.y < span.y)
3426 if ((next_row != MagickFalse) &&
3427 (number_rows < (ssize_t) image->rows))
3432 p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
3439 indexes=GetCacheViewVirtualIndexQueue(image_view);
3440 for (x=0; x < (ssize_t) image->columns; x++)
3442 if (image->matte != MagickFalse)
3443 alpha=QuantumScale*GetPixelAlpha(p);
3444 x_vector[x].red=alpha*(MagickRealType) GetPixelRed(p);
3445 x_vector[x].green=alpha*(MagickRealType) GetPixelGreen(p);
3446 x_vector[x].blue=alpha*(MagickRealType) GetPixelBlue(p);
3447 if (image->matte != MagickFalse)
3448 x_vector[x].opacity=(MagickRealType) GetPixelOpacity(p);
3449 if (indexes != (IndexPacket *) NULL)
3450 x_vector[x].index=alpha*(MagickRealType)
3451 GetPixelIndex(indexes+x);
3456 for (x=0; x < (ssize_t) image->columns; x++)
3458 y_vector[x].red+=scale.y*x_vector[x].red;
3459 y_vector[x].green+=scale.y*x_vector[x].green;
3460 y_vector[x].blue+=scale.y*x_vector[x].blue;
3461 if (scale_image->matte != MagickFalse)
3462 y_vector[x].opacity+=scale.y*x_vector[x].opacity;
3463 if (scale_indexes != (IndexPacket *) NULL)
3464 y_vector[x].index+=scale.y*x_vector[x].index;
3467 scale.y=(double) scale_image->rows/(
double) image->rows;
3468 next_row=MagickTrue;
3470 if ((next_row != MagickFalse) && (number_rows < (ssize_t) image->rows))
3475 p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
3482 indexes=GetCacheViewVirtualIndexQueue(image_view);
3483 for (x=0; x < (ssize_t) image->columns; x++)
3485 if (image->matte != MagickFalse)
3486 alpha=QuantumScale*GetPixelAlpha(p);
3487 x_vector[x].red=alpha*(MagickRealType) GetPixelRed(p);
3488 x_vector[x].green=alpha*(MagickRealType) GetPixelGreen(p);
3489 x_vector[x].blue=alpha*(MagickRealType) GetPixelBlue(p);
3490 if (image->matte != MagickFalse)
3491 x_vector[x].opacity=(MagickRealType) GetPixelOpacity(p);
3492 if (indexes != (IndexPacket *) NULL)
3493 x_vector[x].index=alpha*(MagickRealType)
3494 GetPixelIndex(indexes+x);
3498 next_row=MagickFalse;
3501 for (x=0; x < (ssize_t) image->columns; x++)
3503 pixel.red=y_vector[x].red+span.y*x_vector[x].red;
3504 pixel.green=y_vector[x].green+span.y*x_vector[x].green;
3505 pixel.blue=y_vector[x].blue+span.y*x_vector[x].blue;
3506 if (image->matte != MagickFalse)
3507 pixel.opacity=y_vector[x].opacity+span.y*x_vector[x].opacity;
3508 if (scale_indexes != (IndexPacket *) NULL)
3509 pixel.index=y_vector[x].index+span.y*x_vector[x].index;
3511 s->green=pixel.green;
3513 if (scale_image->matte != MagickFalse)
3514 s->opacity=pixel.opacity;
3515 if (scale_indexes != (IndexPacket *) NULL)
3516 s->index=pixel.index;
3523 scale.y=(double) scale_image->rows/(
double) image->rows;
3524 next_row=MagickTrue;
3528 if (scale_image->columns == image->columns)
3534 for (x=0; x < (ssize_t) scale_image->columns; x++)
3536 if (scale_image->matte != MagickFalse)
3537 alpha=QuantumScale*GetPixelAlpha(s);
3538 alpha=PerceptibleReciprocal(alpha);
3539 SetPixelRed(q,ClampToQuantum(alpha*s->red));
3540 SetPixelGreen(q,ClampToQuantum(alpha*s->green));
3541 SetPixelBlue(q,ClampToQuantum(alpha*s->blue));
3542 if (scale_image->matte != MagickFalse)
3543 SetPixelOpacity(q,ClampToQuantum(s->opacity));
3544 if (scale_indexes != (IndexPacket *) NULL)
3545 SetPixelIndex(scale_indexes+x,ClampToQuantum(alpha*s->index));
3556 next_column=MagickFalse;
3560 for (x=0; x < (ssize_t) image->columns; x++)
3562 scale.x=(double) scale_image->columns/(
double) image->columns;
3563 while (scale.x >= span.x)
3565 if (next_column != MagickFalse)
3570 pixel.red+=span.x*s->red;
3571 pixel.green+=span.x*s->green;
3572 pixel.blue+=span.x*s->blue;
3573 if (image->matte != MagickFalse)
3574 pixel.opacity+=span.x*s->opacity;
3575 if (scale_indexes != (IndexPacket *) NULL)
3576 pixel.index+=span.x*s->index;
3578 t->green=pixel.green;
3580 if (scale_image->matte != MagickFalse)
3581 t->opacity=pixel.opacity;
3582 if (scale_indexes != (IndexPacket *) NULL)
3583 t->index=pixel.index;
3586 next_column=MagickTrue;
3590 if (next_column != MagickFalse)
3593 next_column=MagickFalse;
3596 pixel.red+=scale.x*s->red;
3597 pixel.green+=scale.x*s->green;
3598 pixel.blue+=scale.x*s->blue;
3599 if (scale_image->matte != MagickFalse)
3600 pixel.opacity+=scale.x*s->opacity;
3601 if (scale_indexes != (IndexPacket *) NULL)
3602 pixel.index+=scale.x*s->index;
3610 pixel.red+=span.x*s->red;
3611 pixel.green+=span.x*s->green;
3612 pixel.blue+=span.x*s->blue;
3613 if (scale_image->matte != MagickFalse)
3614 pixel.opacity+=span.x*s->opacity;
3615 if (scale_indexes != (IndexPacket *) NULL)
3616 pixel.index+=span.x*s->index;
3618 if ((next_column == MagickFalse) &&
3619 ((ssize_t) (t-scale_scanline) < (ssize_t) scale_image->columns))
3622 t->green=pixel.green;
3624 if (scale_image->matte != MagickFalse)
3625 t->opacity=pixel.opacity;
3626 if (scale_indexes != (IndexPacket *) NULL)
3627 t->index=pixel.index;
3633 for (x=0; x < (ssize_t) scale_image->columns; x++)
3635 if (scale_image->matte != MagickFalse)
3636 alpha=QuantumScale*GetPixelAlpha(t);
3637 alpha=PerceptibleReciprocal(alpha);
3638 SetPixelRed(q,ClampToQuantum(alpha*t->red));
3639 SetPixelGreen(q,ClampToQuantum(alpha*t->green));
3640 SetPixelBlue(q,ClampToQuantum(alpha*t->blue));
3641 if (scale_image->matte != MagickFalse)
3642 SetPixelOpacity(q,ClampToQuantum(t->opacity));
3643 if (scale_indexes != (IndexPacket *) NULL)
3644 SetPixelIndex(scale_indexes+x,ClampToQuantum(alpha*t->index));
3649 if (SyncCacheViewAuthenticPixels(scale_view,exception) == MagickFalse)
3654 proceed=SetImageProgress(image,ScaleImageTag,(MagickOffsetType) y,
3656 if (proceed == MagickFalse)
3662 scale_view=DestroyCacheView(scale_view);
3663 image_view=DestroyCacheView(image_view);
3669 if (scale_image->rows != image->rows)
3672 scale_image->type=image->type;
3673 if (status == MagickFalse)
3674 scale_image=DestroyImage(scale_image);
3675 return(scale_image);
3710static void url_encode(
const char *uri,
char *encode_uri)
3716 *hex =
"0123456789ABCDEF";
3718 for (p=encode_uri; *uri !=
'\0'; uri++)
3719 if (((
'a' <= *uri) && (*uri <=
'z')) || ((
'A' <= *uri) && (*uri <=
'Z')) ||
3720 ((
'0' <= *uri) && (*uri <=
'9')) || (strchr(
"/-_.~",*uri) != 0))
3725 *p++=hex[(*uri >> 4) & 0xF];
3726 *p++=hex[*uri & 0xF];
3731MagickExport
Image *ThumbnailImage(
const Image *image,
const size_t columns,
3734#define SampleFactor 5
3737 encode_uri[3*MagickPathExtent+1] =
"/0";
3749 assert(image != (
Image *) NULL);
3750 assert(image->signature == MagickCoreSignature);
3752 assert(exception->signature == MagickCoreSignature);
3753 if (IsEventLogging() != MagickFalse)
3754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3755 thumbnail_image=CloneImage(image,0,0,MagickTrue,exception);
3756 if (thumbnail_image == (
Image *) NULL)
3757 return(thumbnail_image);
3758 if ((columns != image->columns) || (rows != image->rows))
3761 *clone_image = thumbnail_image;
3767 x_factor=(ssize_t) image->columns/(ssize_t) columns;
3768 y_factor=(ssize_t) image->rows/(ssize_t) rows;
3769 if ((x_factor > 4) && (y_factor > 4))
3771 thumbnail_image=SampleImage(clone_image,4*columns,4*rows,exception);
3772 if (thumbnail_image != (
Image *) NULL)
3774 clone_image=DestroyImage(clone_image);
3775 clone_image=thumbnail_image;
3778 if ((x_factor > 2) && (y_factor > 2))
3780 thumbnail_image=ResizeImage(clone_image,2*columns,2*rows,BoxFilter,
3782 if (thumbnail_image != (
Image *) NULL)
3784 clone_image=DestroyImage(clone_image);
3785 clone_image=thumbnail_image;
3788 thumbnail_image=ResizeImage(clone_image,columns,rows,image->filter ==
3789 UndefinedFilter ? LanczosSharpFilter : image->filter,1.0,exception);
3790 clone_image=DestroyImage(clone_image);
3791 if (thumbnail_image == (
Image *) NULL)
3792 return(thumbnail_image);
3794 (void) ParseAbsoluteGeometry(
"0x0+0+0",&thumbnail_image->page);
3795 thumbnail_image->depth=8;
3796 thumbnail_image->interlace=NoInterlace;
3800 ResetImageProfileIterator(thumbnail_image);
3801 for (name=GetNextImageProfile(thumbnail_image); name != (
const char *) NULL; )
3803 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
3805 (void) DeleteImageProfile(thumbnail_image,name);
3806 ResetImageProfileIterator(thumbnail_image);
3808 name=GetNextImageProfile(thumbnail_image);
3810 (void) DeleteImageProperty(thumbnail_image,
"comment");
3811 url_encode(image->filename,encode_uri);
3812 if (*image->filename !=
'/')
3813 (void) FormatImageProperty(thumbnail_image,
"Thumb::URI",
"./%s",encode_uri);
3815 (
void) FormatImageProperty(thumbnail_image,
"Thumb::URI",
"file://%s",
3817 if (GetPathAttributes(image->filename,&attributes) != MagickFalse )
3818 (void) FormatImageProperty(thumbnail_image,
"Thumb::MTime",
"%.20g",(
double)
3819 attributes.st_mtime);
3820 (void) FormatImageProperty(thumbnail_image,
"Thumb::Size",
"%.20g",
3821 (
double) GetBlobSize(image));
3822 mime_type=GetImageProperty(image,
"mime:type");
3823 if (mime_type != (
const char *) NULL)
3824 (void) SetImageProperty(thumbnail_image,
"Thumb::Mimetype",mime_type);
3825 (void) SetImageProperty(thumbnail_image,
"software",MagickAuthoritativeURL);
3826 (void) FormatImageProperty(thumbnail_image,
"Thumb::Image::Width",
"%.20g",
3827 (
double) image->magick_columns);
3828 (void) FormatImageProperty(thumbnail_image,
"Thumb::Image::Height",
"%.20g",
3829 (
double) image->magick_rows);
3830 (void) FormatImageProperty(thumbnail_image,
"Thumb::Document::Pages",
"%.20g",
3831 (
double) GetImageListLength(image));
3832 return(thumbnail_image);