% Blackman Hanning Hamming
% Kaiser Lanczos
%
+% Special purpose Filters
+% SincFast Lanczos2D
+%
% The users "-filter" selection is used to lookup the default 'expert'
% settings for that filter from a internal table. However any provided
% 'expert' settings (see below) may override this selection.
% and rational (high Q) approximations, and will be used by default in
% most cases.
%
+% The Lanczos2D filter is just a normal 2-lobed Lanczos filter. But if
+% selected as a cylindrical (radial) filter, the 2-lobed Jinc windowed
+% Jinc will be modified by a blur factor to negate the effect of windowing
+% the Jinc function, and greatly reduce resulting blur.
+%
% Special 'expert' options can be used to override any and all filter
% settings. This is not advised unless you have expert knowledge of
% the use of resampling filtered techniques. Check on the results of
% your selections using the "filter:verbose" setting to make sure you
-% got what you requested.
+% get the exact filter that you are tring to achieve.
%
% "filter:filter" Select the main function associated with
% this filter name, as the weighting function of the filter.
{ SincFastFilter, BohmanFilter }, /* Bohman -- 2*cosine-sinc */
{ SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */
{ SincFastFilter, BoxFilter }, /* Raw fast sinc ("Pade"-type) */
+ { Lanczos2DFilter, JincFilter }, /* SPECIAL: 2-lobed jinc-jinc */
};
/*
Table mapping the filter/window from the above table to an actual
{
MagickRealType
(*function)(const MagickRealType, const ResizeFilter*),
- support, /* default support size for function as a weighting filter */
+ lobes, /* default lobes/support size of the weighting filter */
scale, /* windowing function range, for scaling windowing function */
B,C; /* Cubic Filter factors for a CubicBC function, else ignored */
} const filters[SentinelFilter] =
{
- { Box, 0.5, 0.5, 0.0, 0.0 }, /* Undefined (default to Box) */
- { Box, 0.0, 0.5, 0.0, 0.0 }, /* Point (special handling) */
- { Box, 0.5, 0.5, 0.0, 0.0 }, /* Box */
- { Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Triangle */
- { CubicBC, 1.0, 1.0, 0.0, 0.0 }, /* Hermite (cubic B=C=0) */
- { Hanning, 1.0, 1.0, 0.0, 0.0 }, /* Hanning, cosine window */
- { Hamming, 1.0, 1.0, 0.0, 0.0 }, /* Hamming, '' variation */
- { Blackman, 1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window */
- { Gaussian, 1.5, 1.5, 0.0, 0.0 }, /* Gaussian */
- { Quadratic, 1.5, 1.5, 0.0, 0.0 }, /* Quadratic gaussian */
- { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
- { CubicBC, 2.0, 1.0, 0.0, 0.5 }, /* Catmull-Rom (B=0,C=1/2) */
- { CubicBC, 2.0, 1.0, 1./3., 1./3. }, /* Mitchell (B=C=1/3) */
- { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, 3-lobed sinc-sinc */
- { Jinc, 3.2383, 1.2197, 0.0, 0.0 }, /* Raw 3-lobed Jinc */
- { Sinc, 4.0, 1.0, 0.0, 0.0 }, /* Raw 4-lobed Sinc */
- { Kaiser, 1.0, 1.0, 0.0, 0.0 }, /* Kaiser (square root window) */
- { Welsh, 1.0, 1.0, 0.0, 0.0 }, /* Welsh (parabolic window) */
- { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Parzen (B-Spline window) */
- { Lagrange, 2.0, 1.0, 0.0, 0.0 }, /* Lagrange sinc approximation */
- { Bohman, 1.0, 1.0, 0.0, 0.0 }, /* Bohman, 2*Cosine window */
- { Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Bartlett (triangle window) */
- { SincFast, 4.0, 1.0, 0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
+ { Box, 0.5, 0.5, 0.0, 0.0 }, /* Undefined (default to Box) */
+ { Box, 0.0, 0.5, 0.0, 0.0 }, /* Point (special handling) */
+ { Box, 0.5, 0.5, 0.0, 0.0 }, /* Box */
+ { Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Triangle */
+ { CubicBC, 1.0, 1.0, 0.0, 0.0 }, /* Hermite (cubic B=C=0) */
+ { Hanning, 1.0, 1.0, 0.0, 0.0 }, /* Hanning, cosine window */
+ { Hamming, 1.0, 1.0, 0.0, 0.0 }, /* Hamming, '' variation */
+ { Blackman, 1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window */
+ { Gaussian, 1.5, 1.5, 0.0, 0.0 }, /* Gaussian */
+ { Quadratic, 1.5, 1.5, 0.0, 0.0 }, /* Quadratic gaussian */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
+ { CubicBC, 2.0, 1.0, 0.0, 0.5 }, /* Catmull-Rom (B=0,C=1/2) */
+ { CubicBC, 2.0, 1.0, 1./3., 1./3. }, /* Mitchell (B=C=1/3) */
+ { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, 3-lobed sinc-sinc */
+ { Jinc, 3.0, 1.21967, 0.0, 0.0 }, /* Raw 3-lobed Jinc */
+ { Sinc, 4.0, 1.0, 0.0, 0.0 }, /* Raw 4-lobed Sinc */
+ { Kaiser, 1.0, 1.0, 0.0, 0.0 }, /* Kaiser (square root window) */
+ { Welsh, 1.0, 1.0, 0.0, 0.0 }, /* Welsh (parabolic window) */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Parzen (B-Spline window) */
+ { Lagrange, 2.0, 1.0, 0.0, 0.0 }, /* Lagrange sinc approximation */
+ { Bohman, 1.0, 1.0, 0.0, 0.0 }, /* Bohman, 2*Cosine window */
+ { Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Bartlett (triangle window) */
+ { SincFast, 4.0, 1.0, 0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
+ { Jinc, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos2D, adjusted below */
};
/*
The known zero crossings of the Jinc() or more accuritally the Jinc(x*PI)
if ( filter != SincFastFilter )
filter_type=JincFilter;
break;
+
case LanczosFilter:
/* Promote Lanczos from a Sinc-Sinc to a Jinc-Jinc */
filter_type=JincFilter;
window_type=JincFilter;
break;
default:
- /*
- What about other filters to make them 'cylindrical friendly'?
- For example Mitchell is already actually quite close to a
- cylindrical Lanczos (Jinc-Jinc) with support 2. Are there
- other well known 'cylindrical' specific filters?
- */
break;
}
+ else
+ switch (filter_type)
+ {
+ case Lanczos2DFilter:
+ /* depromote to a 2-lobe Sinc-Sinc for orthoginal use */
+ window_type=SincFastFilter;
+ break;
+ default:
+ break;
+ }
+
artifact=GetImageArtifact(image,"filter:filter");
if (artifact != (const char *) NULL)
{
option=ParseMagickOption(MagickFilterOptions,MagickFalse,artifact);
if ((UndefinedFilter < option) && (option < SentinelFilter))
- {
- /* Raw filter request - no window function. */
+ { /* Raw filter request - no window function. */
filter_type=(FilterTypes) option;
window_type=BoxFilter;
}
if (option == LanczosFilter)
- {
- /* Lanczos is not a real filter but a self windowing Sinc/Jinc. */
- filter_type=cylindrical != MagickFalse ? JincFilter : LanczosFilter;
+ { /* Lanczos is not a real filter but a self windowing Sinc/Jinc. */
+ filter_type=cylindrical != MagickFalse ? JincFilter : Lanczos2DFilter;
window_type=cylindrical != MagickFalse ? JincFilter : SincFastFilter;
}
/* Filter override with a specific window function. */
artifact);
if ((UndefinedFilter < option) && (option < SentinelFilter))
{
- filter_type=cylindrical != MagickFalse ? JincFilter :
- SincFastFilter;
+ filter_type=cylindrical != MagickFalse ?
+ JincFilter : SincFastFilter;
window_type=(FilterTypes) option;
}
}
}
/* Assign the real functions to use for the filters selected. */
resize_filter->filter=filters[filter_type].function;
- resize_filter->support=filters[filter_type].support;
+ resize_filter->support=filters[filter_type].lobes;
resize_filter->window=filters[window_type].function;
resize_filter->scale=filters[window_type].scale;
resize_filter->signature=MagickSignature;
+
/* Filter blur -- scaling both filter and support window. */
resize_filter->blur=blur;
artifact=GetImageArtifact(image,"filter:blur");
resize_filter->blur *= MagickSQ2;
resize_filter->support = (MagickRealType) MagickSQ2; /* which times blur => 2.0 */
break;
+ case Lanczos2DFilter:
+ /* Special 2 lobed cylindrical Jinc-Jinc filter,
+ * with a special blur adjustment to remove the blurring effect
+ * of the windowing of the Jinc function (in the 2 lobed case only).
+ * To be used as the default filter for EWA Resampling and Distorts.
+ */
+ resize_filter->blur *= (MagickRealType) 0.9549921738;
+ default:
+ break;
+ }
+ else
+ switch (filter_type)
+ {
+ case Lanczos2DFilter:
+ /* depromote to a 2-lobe Sinc-Sinc for orthoginal use */
+ resize_filter->filter=SincFast;
+ break;
default:
break;
}
+
/* Filter support overrides. */
artifact=GetImageArtifact(image,"filter:lobes");
if (artifact != (const char *) NULL)
if (lobes < 1)
lobes=1;
resize_filter->support=(MagickRealType) lobes;
- if (filter_type == JincFilter)
- {
- if (lobes > 16)
- lobes=16;
- resize_filter->support = jinc_zeros[lobes-1];
- }
}
+ /* convert Jinc lobes to a real support value */
+ if (resize_filter->filter == Jinc)
+ {
+ if (resize_filter->support > 16)
+ resize_filter->support=jinc_zeros[15]; /* largest entry in table */
+ else
+ resize_filter->support = jinc_zeros[((long)resize_filter->support)-1];
+ }
+ /* expert override of the support setting */
artifact=GetImageArtifact(image,"filter:support");
if (artifact != (const char *) NULL)
resize_filter->support=fabs(StringToDouble(artifact));
Expert Option Request for verbose details of the resulting filter.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- /* if( GetOpenMPThreadId() == 0 ) { */
+ if( GetOpenMPThreadId() == 0 ) {
#endif
artifact=GetImageArtifact(image,"filter:verbose");
if (artifact != (const char *) NULL)
if (resize_filter->filter == Box) filter_type=BoxFilter;
if (resize_filter->filter == Sinc) filter_type=SincFilter;
if (resize_filter->filter == SincFast) filter_type=SincFastFilter;
+ if (resize_filter->filter == Jinc) filter_type=JincFilter;
if (resize_filter->filter == CubicBC) filter_type=CubicFilter;
/*
Report Filter Details.
*/
support=GetResizeFilterSupport(resize_filter); /* support range */
- (void) fprintf(stdout,"#\n# Resize Filter (for graphing)\n#\n");
+ (void) fprintf(stdout,"# Resize Filter (for graphing)\n#\n");
(void) fprintf(stdout,"# filter = %s\n",MagickOptionToMnemonic(
MagickFilterOptions,filter_type));
(void) fprintf(stdout,"# window = %s\n",MagickOptionToMnemonic(
(double) support);
(void) fprintf(stdout,"# B,C = %.*g,%.*g\n",GetMagickPrecision(),
(double) B,GetMagickPrecision(),(double) C);
- (void) fprintf(stdout,"#\n");
+ (void) fprintf(stdout,"\n");
/*
Output values of resulting filter graph -- for graphing
filter result.
0.0);
}
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- /* } */
+ }
#endif
return(resize_filter);
}