From: anthony Date: Fri, 8 Oct 2010 06:01:31 +0000 (+0000) Subject: change filter "Lanczos2D" add filter "Robidoux" (both hidden) X-Git-Tag: 7.0.1-0~8724 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=853d6979aa2981592af7020163b5030aa7185783;p=imagemagick change filter "Lanczos2D" add filter "Robidoux" (both hidden) --- diff --git a/ChangeLog b/ChangeLog index e7809e076..0aa9b9bd6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ 2010-10-05 6.6.4-10 Anthony Thyssen - * Added new filter 'Lanczos2D' a 2-lobe Lanczos with a optimization - specifically for cylindrical Jinc-Jinc usage. + * Added new filter 'Lanczos2D' a 2-lobe Lanczos as defined by + Andreas Gustafsson in his thesis "Interactive Image Warping" (page 24) + http://www.gson.org/thesis/warping-thesis.pdf + * Added filter "Robidoux" whcih is a 'negativally' blurred version + of the "Lanczos2D" filter specifically designed to be less 'blurry' + for horizontal and vertical lines in no-op distortions. + It is now the default filter (if none specified) for EWA resampling. 2010-10-05 6.6.4-10 Cristy * Add support for "pattern:vertical2" and "pattern:horizontal2". diff --git a/magick/option.c b/magick/option.c index b5ffe5c34..1134efb87 100644 --- a/magick/option.c +++ b/magick/option.c @@ -945,7 +945,6 @@ static const OptionInfo { "Hanning", (ssize_t) HanningFilter, MagickFalse }, { "Hermite", (ssize_t) HermiteFilter, MagickFalse }, { "Jinc", (ssize_t) JincFilter, MagickFalse }, - { "Bessel", (ssize_t) JincFilter, MagickTrue }, /* Set it after "Jinc" */ { "Kaiser", (ssize_t) KaiserFilter, MagickFalse }, { "Lagrange", (ssize_t) LagrangeFilter, MagickFalse }, { "Lanczos", (ssize_t) LanczosFilter, MagickFalse }, @@ -954,10 +953,14 @@ static const OptionInfo { "Parzen", (ssize_t) ParzenFilter, MagickFalse }, { "Point", (ssize_t) PointFilter, MagickFalse }, { "Quadratic", (ssize_t) QuadraticFilter, MagickFalse }, + { "Robidoux", (ssize_t) RobidouxFilter, MagickTrue }, { "Sinc", (ssize_t) SincFilter, MagickFalse }, { "SincFast", (ssize_t) SincFastFilter, MagickFalse }, { "Triangle", (ssize_t) TriangleFilter, MagickFalse }, + { "Tent", (ssize_t) TriangleFilter, MagickFalse }, { "Welsh", (ssize_t) WelshFilter, MagickFalse }, + /* For backward compatibility - set after "Jinc" */ + { "Bessel", (ssize_t) JincFilter, MagickTrue }, { (char *) NULL, (ssize_t) UndefinedFilter, MagickFalse } }, FunctionOptions[] = diff --git a/magick/resample.c b/magick/resample.c index d41f94022..b2e2246fa 100644 --- a/magick/resample.c +++ b/magick/resample.c @@ -1770,7 +1770,7 @@ MagickExport void SetResampleFilter(ResampleFilter *resample_filter, /* Set a default cylindrical filter of a 'low blur' Jinc windowed Jinc */ if ( filter == UndefinedFilter ) - resample_filter->filter = MitchellFilter; + resample_filter->filter = RobidouxFilter; resize_filter = AcquireResizeFilter(resample_filter->image, resample_filter->filter,blur,MagickTrue,resample_filter->exception); diff --git a/magick/resample.h b/magick/resample.h index faddfad4b..b72d62dce 100644 --- a/magick/resample.h +++ b/magick/resample.h @@ -56,6 +56,7 @@ typedef enum BartlettFilter, SincFastFilter, Lanczos2DFilter, + RobidouxFilter, SentinelFilter /* a count of all the filters, not a real filter */ } FilterTypes; diff --git a/magick/resize.c b/magick/resize.c index 096c0647c..fc5f84d21 100644 --- a/magick/resize.c +++ b/magick/resize.c @@ -415,7 +415,7 @@ static MagickRealType SincFast(const MagickRealType x, const MagickRealType c7 = -0.187208577776590710853865174371617338991e-11L; const MagickRealType c8 = 0.253524321426864752676094495396308636823e-13L; const MagickRealType c9 = -0.177084805010701112639035485248501049364e-15L; - const MagickRealType p = + const MagickRealType p = c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*(c7+xx*(c8+xx*c9)))))))); return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p); #else @@ -493,7 +493,7 @@ static MagickRealType Welsh(const MagickRealType x, % Kaiser Lanczos % % Special purpose Filters -% SincFast Lanczos2D +% SincFast Lanczos2D Robidoux % % The users "-filter" selection is used to lookup the default 'expert' % settings for that filter from a internal table. However any provided @@ -526,10 +526,10 @@ static MagickRealType Welsh(const MagickRealType x, % and rational (high Q) approximations, and will be used by default in % most cases. % -% The Lanczos2D filter is often just a normal 2-lobed Lanczos -% filter. If selected as a cylindrical (radial) filter, the support -% of the 2-lobed Jinc windowed Jinc is modified (through the blur -% property) in order to make the results sharper. +% The Lanczos2D filter is just 2-lobed Lanczos using Sinc/Jinc as +% appropriate. The Robidoux is the same thing but is modified (through +% the blur setting) in order to make the results sharper in the 'no-op' case. +% (see notes below) % % Special 'expert' options can be used to override any and all filter % settings. This is not advised unless you have expert knowledge of @@ -680,6 +680,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */ { SincFastFilter, BoxFilter }, /* Raw fast sinc ("Pade"-type) */ { Lanczos2DFilter, JincFilter }, /* SPECIAL: 2-lobed jinc-jinc */ + { RobidouxFilter, JincFilter }, /* SPECIAL: Lanzcos2D blurred */ }; /* Table mapping the filter/window from the above table to an actual @@ -715,9 +716,9 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { 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 */ + { 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) */ @@ -726,7 +727,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { 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 */ + { Jinc, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos2D, Jinc-Jinc */ + { Jinc, 2.0, 1.0, 0.0, 0.0 }, /* Robidoux, blured Jinc-Jinc */ }; /* The known zero crossings of the Jinc() or more accurately the @@ -823,7 +825,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, } if (option == LanczosFilter) { /* Lanczos is not a real filter but a self windowing Sinc/Jinc. */ - filter_type=cylindrical != MagickFalse ? JincFilter : Lanczos2DFilter; + filter_type=cylindrical != MagickFalse ? JincFilter : LanczosFilter; window_type=cylindrical != MagickFalse ? JincFilter : SincFastFilter; } /* Filter override with a specific window function. */ @@ -888,66 +890,60 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, 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 (actually, a "negative blur," since the - * support is scaled to make it slightly smaller, with the - * consequence that the results are slightly sharper). - * - * Used as default filter for EWA Resampling and Distorts. - * - * Executive summary: - * - * This is the closest a two-lobe Jinc-Jinc used radially - * (with Clamped EWA) comes to preserving straight - * vertical---and straight horizontal---features. - * - * Details: + case RobidouxFilter: + /* Special 2-lobed cylindrical Jinc-Jinc filter created by Nicolas + * Robidoux, Professor of Mathematics, Laurentian University. + * + * It is a "blur" (negative blur actually) adjusted 2-lobed + * Jinc-windowed-Jinc Cylindrical (radial) filter, designed to + * preserve straight vertical and horizontal features. + * + * Given the "Lanczos2D" filter defined by Andreas Gustafsson in his + * "Interactive Image Warping" (page 24) + * http://www.gson.org/thesis/warping-thesis.pdf + * + * Lanczos2D(x) = Jinc(x)*Jinc(x*r1/r2) with support r2 + * + * (where r1 is the first root of the Jinc function, and r2 is the + * second), rescale the filter by a value 's'. + * + * Robidoux(x) = Lanczos2D(s*x) with support r2/s * - * Basically, this is the standard - * - * Lanczos2D(x) = Jinc(x)*Jinc(x*r1/r2) with support r2 - * - * (where r1 is the first root of the Jinc function, and r2 is - * the second) rescaled so that images which are constant in - * the vertical direction, and images which are constant in - * the horizontal direction, are almost unchanged (the change - * being generically as small as possible) when the - * geometrical transformation applied to the image is is the - * identity (a.k.a. "no-op"). - * - * Specifically, it is Lanczos2D(s*x) with support r2/s, where - * s is chosen so that + * the value 's' is chossen so that images which are constant in the + * vertical direction, and images which are constant in the horizontal + * direction, are almost unchanged (the change being generically as + * small as possible) when the geometrical transformation applied to + * the image is the identity (a.k.a. "no-op" or no scaling ). * - * Lanczos2D(s)=-2*Lanczos2D(s*sqrt(2))-Lanczos2D(s*2). - * - * This value of s ensures that the value of a one-pixel-wide - * vertical line (equal to 1, say, on a black=0 background) is - * exactly preserved when no-op is applied to the image. It - * also ensures that---with no-op---the nearest two columns on - * either side are minimally changed (the farther columns are - * unchanged no matter what). Specifically, the nearest - * columns on the left and the right have values raised from - * zero to c, and the second closest columns on the left and - * right are lowered from 0 to minus c. (That is, the very - * closest columns are made slightly positive, and the second - * closest are made slightly negative, in equal amounts.) The - * size c of this blur/halo is .002042317. Consequently, image - * values between 0 and M which are constant on columns (or - * rows) are preserved by no-op to within 2Mc (less than one - * half of one percent of the dynamic range). - * - * Note that "high frequency modes" which are not aligned with - * image rows or columns are damped considerably. For example, - * the amplitude of the very highest energy mode, the - * so-called "checkerboard" mode, is reduced by almost 62% - * (still less than with "standard" Lanczos2D or with a - * comparable Gaussian kernel). - * - * This "optimal" scaling was discovered by Nicolas Robidoux - * of Laurentian University. - * - * Below, resize_filter->blur is 1/s. + * As such this formula needs to hold true + * + * Lanczos2D(s)=-2*Lanczos2D(s*sqrt(2))-Lanczos2D(s*2). + * + * This value of s ensures that the value of a one-pixel-wide vertical + * line (equal to 1, say, on a black=0 background) is exactly + * preserved when no-op is applied to the image. It also ensures + * that, in the no-op case, the nearest two columns on either side are + * minimally changed (the farther columns are unchanged no matter + * what). Specifically, the nearest columns on the left and the right + * have values raised from zero to c, and the second closest columns + * on the left and right are lowered from 0 to minus c. That is, the + * very closest columns are made slightly positive, and the second + * closest are made slightly negative, in equal amounts. The size c + * of this blur/halo is .002042317. Consequently, image values + * between 0 and M which are constant on columns (or rows) are + * preserved by no-op to within 2Mc (less than one half of one percent + * of the dynamic range). + * + * Note that "high frequency modes" which are not aligned with image + * rows or columns are damped considerably. For example, the amplitude + * of the very highest energy mode, the so-called "checkerboard" mode, + * is reduced by almost 62% (still less than with "standard" Lanczos2D + * or with a comparable Gaussian kernel). + * + * This "optimal" scaling was discovered by Nicolas Robidoux of + * Laurentian University. + * + * Below, resize_filter->blur is 1/s. */ resize_filter->blur *= (MagickRealType) 0.958033808; default: @@ -957,7 +953,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, switch (filter_type) { case Lanczos2DFilter: - /* Demote to a 2-lobe Sinc-Sinc for orthogonal use. */ + case RobidouxFilter: + /* Demote to a 2-lobe Lanczos (Sinc-Sinc) for orthogonal use. */ resize_filter->filter=SincFast; break; default: