From a127d7d39129ee648c7676d3c736b0700aa92a12 Mon Sep 17 00:00:00 2001 From: Ben Arthur Date: Fri, 24 Oct 2025 17:13:47 -0400 Subject: [PATCH 1/4] reduced precision for lanczos_opencv --- src/lanczos/lanczos_opencv.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lanczos/lanczos_opencv.jl b/src/lanczos/lanczos_opencv.jl index 62f350df..556847a2 100644 --- a/src/lanczos/lanczos_opencv.jl +++ b/src/lanczos/lanczos_opencv.jl @@ -65,20 +65,21 @@ const s45 = 0.70710678118654752440084436210485 const l4_2d_cs = SA[1 0; -s45 -s45; 0 1; s45 -s45; -1 0; s45 s45; 0 -1; -s45 s45] -function _lanczos4_opencv(δx) - p_4 = π / 4 +function _lanczos4_opencv(δx::T) where T + F = float(T) + p_4 = π / F(4) y0 = -(δx + 3) * p_4 - s0, c0 = sincos(y0) + s0::F, c0::F = sincos(y0) cs = ntuple(8) do i y = (δx + 4 - i) * p_4 # Improve precision of Lanczos OpenCV4 #451, avoid NaN if iszero(y) - y = eps(oneunit(y))/8 + y = eps(oneunit(y))/F(8) end # Numerator is the sin subtraction identity # It is equivalent to the following # f(δx,i) = sin( π/4*( 5*(i-1)-δx-3 ) ) - (l4_2d_cs[i, 1] * s0 + l4_2d_cs[i, 2] * c0) / y^2 + (F(l4_2d_cs[i, 1]) * s0 + F(l4_2d_cs[i, 2]) * c0) / y^2 end sum_cs = sum(cs) normed_cs = ntuple(i -> cs[i] / sum_cs, Val(8)) From 5f69ead662058083dbb42c635f342e5ba2721275 Mon Sep 17 00:00:00 2001 From: Ben Arthur Date: Fri, 24 Oct 2025 17:41:06 -0400 Subject: [PATCH 2/4] function barrier for float(F) --- src/lanczos/lanczos_opencv.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lanczos/lanczos_opencv.jl b/src/lanczos/lanczos_opencv.jl index 556847a2..fd04c34d 100644 --- a/src/lanczos/lanczos_opencv.jl +++ b/src/lanczos/lanczos_opencv.jl @@ -54,7 +54,8 @@ struct Lanczos4OpenCV <: AbstractLanczos end degree(::Lanczos4OpenCV) = 4 -value_weights(::Lanczos4OpenCV, δx) = _lanczos4_opencv(δx) +value_weights(::Lanczos4OpenCV, δx::T) where {T} = + _lanczos4_opencv(float(T), float(T).(l4_2d_cs), δx) # s45 = sqrt(2)/2 const s45 = 0.70710678118654752440084436210485 @@ -65,8 +66,7 @@ const s45 = 0.70710678118654752440084436210485 const l4_2d_cs = SA[1 0; -s45 -s45; 0 1; s45 -s45; -1 0; s45 s45; 0 -1; -s45 s45] -function _lanczos4_opencv(δx::T) where T - F = float(T) +function _lanczos4_opencv(::Type{F}, l4_2d_cs, δx) where {F} p_4 = π / F(4) y0 = -(δx + 3) * p_4 s0::F, c0::F = sincos(y0) From 6dfc81456e441899bec414711a8e5967df0fce2f Mon Sep 17 00:00:00 2001 From: Ben Arthur Date: Mon, 27 Oct 2025 18:20:26 -0400 Subject: [PATCH 3/4] specify lanczos precision in type parameter --- src/lanczos/lanczos_opencv.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lanczos/lanczos_opencv.jl b/src/lanczos/lanczos_opencv.jl index fd04c34d..7433b08d 100644 --- a/src/lanczos/lanczos_opencv.jl +++ b/src/lanczos/lanczos_opencv.jl @@ -50,11 +50,12 @@ export Lanczos4OpenCV Alternative implementation of Lanczos resampling using algorithm `lanczos4` function of OpenCV: https://github.com/opencv/opencv/blob/de15636724967faf62c2d1bce26f4335e4b359e5/modules/imgproc/src/resize.cpp#L917-L946 """ -struct Lanczos4OpenCV <: AbstractLanczos end +struct Lanczos4OpenCV{T} <: AbstractLanczos end +Lanczos4OpenCV() = Lanczos4OpenCV{Float64}() degree(::Lanczos4OpenCV) = 4 -value_weights(::Lanczos4OpenCV, δx::T) where {T} = +value_weights(::Lanczos4OpenCV{T}, δx) where {T} = _lanczos4_opencv(float(T), float(T).(l4_2d_cs), δx) # s45 = sqrt(2)/2 From 740fa93b6baa857fb7007a931cd0c57f11095fdb Mon Sep 17 00:00:00 2001 From: Ben Arthur Date: Mon, 27 Oct 2025 18:21:21 -0400 Subject: [PATCH 4/4] more faithfully follow opencv's lanczos code --- src/lanczos/lanczos_opencv.jl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/lanczos/lanczos_opencv.jl b/src/lanczos/lanczos_opencv.jl index 7433b08d..e1a3d11d 100644 --- a/src/lanczos/lanczos_opencv.jl +++ b/src/lanczos/lanczos_opencv.jl @@ -68,19 +68,17 @@ const l4_2d_cs = SA[1 0; -s45 -s45; 0 1; s45 -s45; -1 0; s45 s45; 0 -1; -s45 s45 function _lanczos4_opencv(::Type{F}, l4_2d_cs, δx) where {F} - p_4 = π / F(4) - y0 = -(δx + 3) * p_4 - s0::F, c0::F = sincos(y0) + p_4 = π * F(0.25) + y0 = -(δx + F(3)) * p_4 + s0, c0 = sincos(y0) cs = ntuple(8) do i - y = (δx + 4 - i) * p_4 - # Improve precision of Lanczos OpenCV4 #451, avoid NaN - if iszero(y) - y = eps(oneunit(y))/F(8) + y = δx + 4 - i + if abs(y) >= F(1e-6) + y *= p_4 + (F(l4_2d_cs[i, 1]) * s0 + F(l4_2d_cs[i, 2]) * c0) / y^2 + else + F(1e30) end - # Numerator is the sin subtraction identity - # It is equivalent to the following - # f(δx,i) = sin( π/4*( 5*(i-1)-δx-3 ) ) - (F(l4_2d_cs[i, 1]) * s0 + F(l4_2d_cs[i, 2]) * c0) / y^2 end sum_cs = sum(cs) normed_cs = ntuple(i -> cs[i] / sum_cs, Val(8))