Skip to content

Commit 6466463

Browse files
committed
upgrade legacy argument dispatch methods with cleaner keyword version
1 parent 9257562 commit 6466463

File tree

13 files changed

+399
-345
lines changed

13 files changed

+399
-345
lines changed

Project.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ version = "0.8.12"
66
AxisAlgorithms = "13072b0f-2c55-5437-9ae7-d433b7a33950"
77
ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4"
88
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
9-
IdentityRanges = "bbac6d45-d8f3-5730-bfe4-7a449cd117ca"
109
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
1110
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
1211
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
@@ -17,7 +16,6 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1716
AxisAlgorithms = "1.0"
1817
ColorVectorSpace = "0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9"
1918
CoordinateTransformations = "0.5, 0.6"
20-
IdentityRanges = "0.3"
2119
ImageCore = "0.8.1, 0.9"
2220
Interpolations = "0.9, 0.10, 0.11, 0.12, 0.13"
2321
OffsetArrays = "0.10, 0.11, 1.0.1"

src/ImageTransformations.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ using StaticArrays
77
using Interpolations, AxisAlgorithms
88
using OffsetArrays
99
using ColorVectorSpace
10-
using IdentityRanges
1110

1211
import Base: eltype, size, length
1312
using Base: tail, Indices
@@ -32,7 +31,10 @@ include("interpolations.jl")
3231
include("warp.jl")
3332
include("warpedview.jl")
3433
include("invwarpedview.jl")
34+
include("compat.jl")
35+
include("deprecated.jl")
3536

37+
# TODO: move to warp.jl
3638
@inline _getindex(A, v::StaticVector) = A[Tuple(v)...]
3739
@inline _getindex(A::AbstractInterpolation, v::StaticVector) = A(Tuple(v)...)
3840
@inline _getindex(A, v) = A[v...]

src/autorange.jl

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
1-
function autorange(img, tform)
2-
R = CartesianIndices(axes(img))
3-
autorange(R, tform)
4-
end
1+
"""
2+
autorange(A::AbstractArray, tform::Transformation)
3+
4+
For given transformation `tform`, return the "smallest" range indices that
5+
preserves all information from `A` after applying `tform`.
6+
7+
# Examples
8+
9+
For transformation that preserves the array size, `autorange` is equivalent to `axes(A)`.
10+
11+
```jldoctest; setup=:(using ImageTransformations: autorange; using CoordinateTransformations, Rotations, ImageTransformations)
12+
A = rand(5, 5)
13+
tform = IdentityTransformation()
14+
autorange(A, tform) == axes(A)
515
16+
# output
17+
true
18+
```
19+
20+
The diffrence shows up when `tform` enlarges the input array `A`. In the following example, we need
21+
at least `(0:6, 0:6)` as the range indices to get all data of `A`:
22+
23+
```jldoctest; setup=:(using ImageTransformations: autorange; using CoordinateTransformations, Rotations, ImageTransformations)
24+
A = rand(5, 5)
25+
tform = recenter(RotMatrix(pi/8), center(A))
26+
autorange(A, tform)
27+
28+
# output
29+
(0:6, 0:6)
30+
```
31+
32+
!!! note
33+
This function is not exported; it is mainly for internal usage to infer the default indices.
34+
"""
35+
autorange(A::AbstractArray, tform) = autorange(CartesianIndices(A), tform)
636
function autorange(R::CartesianIndices, tform)
737
tform = _round(tform)
838
mn = mx = tform(SVector(first(R).I))
@@ -91,9 +121,6 @@ function _round(tform::T; kwargs...) where T<:CoordinateTransformations.Transfor
91121
end
92122
T(rounded_fields...)
93123
end
94-
if isdefined(Base, :ComposedFunction)
95-
_round(tform::ComposedFunction; kwargs...) = _round(tform.outer; kwargs...) _round(tform.inner; kwargs...)
96-
end
97124
_round(tform; kwargs...) = tform
98125

99126
__round(x; kwargs...) = x

src/compat.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This file includes two kinds of codes
2+
# - Codes for backward compatibility
3+
# - Glue codes that might nolonger be necessary in the future
4+
5+
# patch for issue #110
6+
if isdefined(Base, :ComposedFunction) # Julia >= 1.6.0-DEV.85
7+
# https://github.com/JuliaLang/julia/pull/37517
8+
_round(tform::ComposedFunction; kwargs...) = _round(tform.outer; kwargs...) _round(tform.inner; kwargs...)
9+
end
10+
11+
@static if !isdefined(Base, :IdentityUnitRange)
12+
const IdentityUnitRange = Base.Slice
13+
else
14+
using Base: IdentityUnitRange
15+
end
16+
17+
@static if VERSION < v"1.1"
18+
@inline isnothing(x) = x === nothing
19+
end
20+
21+
# FIXME: upstream https://github.com/JuliaGraphics/ColorVectorSpace.jl/issues/75
22+
@inline _nan(::Type{HSV{Float16}}) = HSV{Float16}(NaN16,NaN16,NaN16)
23+
@inline _nan(::Type{HSV{Float32}}) = HSV{Float32}(NaN32,NaN32,NaN32)
24+
@inline _nan(::Type{HSV{Float64}}) = HSV{Float64}(NaN,NaN,NaN)
25+
@inline _nan(::Type{T}) where {T} = nan(T)

src/deprecated.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# BEGIN 0.9 deprecations
2+
3+
@deprecate warp(img::AbstractArray, tform::Transformation, method::MethodType, ) warp(img, tform; method=method)
4+
@deprecate warp(img::AbstractArray, tform::Transformation, fillvalue::FillType) warp(img, tform; fillvalue=fillvalue)
5+
@deprecate warp(img::AbstractArray, tform::Transformation, method::MethodType, fillvalue::FillType) warp(img, tform; method=method, fillvalue=fillvalue)
6+
@deprecate warp(img::AbstractArray, tform::Transformation, fillvalue::FillType, method::MethodType) warp(img, tform; method=method, fillvalue=fillvalue)
7+
@deprecate warp(img::AbstractArray, tform::Transformation, inds, method::MethodType, ) warp(img, tform, inds; method=method)
8+
@deprecate warp(img::AbstractArray, tform::Transformation, inds, fillvalue::FillType) warp(img, tform, inds; fillvalue=fillvalue)
9+
@deprecate warp(img::AbstractArray, tform::Transformation, inds, method::MethodType, fillvalue::FillType) warp(img, tform, inds; method=method, fillvalue=fillvalue)
10+
@deprecate warp(img::AbstractArray, tform::Transformation, inds, fillvalue::FillType, method::MethodType) warp(img, tform, inds; method=method, fillvalue=fillvalue)
11+
12+
@deprecate imrotate(img::AbstractArray, θ::Real, method::MethodType ) imrotate(img, θ; method=method)
13+
@deprecate imrotate(img::AbstractArray, θ::Real, fillvalue::FillType) imrotate(img, θ; fillvalue=fillvalue)
14+
@deprecate imrotate(img::AbstractArray, θ::Real, method::MethodType, fillvalue::FillType) imrotate(img, θ; method=method, fillvalue=fillvalue)
15+
@deprecate imrotate(img::AbstractArray, θ::Real, fillvalue::FillType, method::MethodType) imrotate(img, θ; method=method, fillvalue=fillvalue)
16+
@deprecate imrotate(img::AbstractArray, θ::Real, inds, method::MethodType ) imrotate(img, θ, inds; method=method)
17+
@deprecate imrotate(img::AbstractArray, θ::Real, inds, fillvalue::FillType) imrotate(img, θ, inds; fillvalue=fillvalue)
18+
@deprecate imrotate(img::AbstractArray, θ::Real, inds, method::MethodType, fillvalue::FillType) imrotate(img, θ, inds; method=method, fillvalue=fillvalue)
19+
@deprecate imrotate(img::AbstractArray, θ::Real, inds, fillvalue::FillType, method::MethodType) imrotate(img, θ, inds; method=method, fillvalue=fillvalue)
20+
21+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, method::MethodType, ) WarpedView(img, tform; method=method)
22+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, fillvalue::FillType) WarpedView(img, tform; fillvalue=fillvalue)
23+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, method::MethodType, fillvalue::FillType) WarpedView(img, tform; method=method, fillvalue=fillvalue)
24+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, fillvalue::FillType, method::MethodType) WarpedView(img, tform; method=method, fillvalue=fillvalue)
25+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, inds, method::MethodType, ) WarpedView(img, tform, inds; method=method)
26+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, inds, fillvalue::FillType) WarpedView(img, tform, inds; fillvalue=fillvalue)
27+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, inds, method::MethodType, fillvalue::FillType) WarpedView(img, tform, inds; method=method, fillvalue=fillvalue)
28+
@deprecate WarpedView(img::AbstractArray, tform::Transformation, inds, fillvalue::FillType, method::MethodType) WarpedView(img, tform, inds; method=method, fillvalue=fillvalue)
29+
30+
@deprecate warpedview(args...; kwargs...) WarpedView(args...; kwargs...)
31+
32+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, method::MethodType, ) invwarpedview(img, tinv; method=method)
33+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, fillvalue::FillType) invwarpedview(img, tinv; fillvalue=fillvalue)
34+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, method::MethodType, fillvalue::FillType) invwarpedview(img, tinv; method=method, fillvalue=fillvalue)
35+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, fillvalue::FillType, method::MethodType) invwarpedview(img, tinv; method=method, fillvalue=fillvalue)
36+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, inds, method::MethodType, ) invwarpedview(img, tinv, inds; method=method)
37+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, inds, fillvalue::FillType) invwarpedview(img, tinv, inds; fillvalue=fillvalue)
38+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, inds, method::MethodType, fillvalue::FillType) invwarpedview(img, tinv, inds; method=method, fillvalue=fillvalue)
39+
@deprecate invwarpedview(img::AbstractArray, tinv::Transformation, inds, fillvalue::FillType, method::MethodType) invwarpedview(img, tinv, inds; method=method, fillvalue=fillvalue)
40+
41+
# END 0.9 deprecations

src/interpolations.jl

Lines changed: 21 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,42 @@
1-
# FIXME: upstream https://github.com/JuliaGraphics/ColorVectorSpace.jl/issues/75
2-
@inline _nan(::Type{HSV{Float16}}) = HSV{Float16}(NaN16,NaN16,NaN16)
3-
@inline _nan(::Type{HSV{Float32}}) = HSV{Float32}(NaN32,NaN32,NaN32)
4-
@inline _nan(::Type{HSV{Float64}}) = HSV{Float64}(NaN,NaN,NaN)
5-
@inline _nan(::Type{T}) where {T} = nan(T)
6-
7-
#wraper to deal with degree or interpolation types
1+
# A helper function to let our `method` keyword correctly understands `Degree` inputs.
82
@inline wrap_BSpline(itp::Interpolations.InterpolationType) = itp
93
@inline wrap_BSpline(degree::Interpolations.Degree) = BSpline(degree)
104

115
# The default values used by extrapolation for off-domain points
126
const FillType = Union{Number,Colorant,Flat,Periodic,Reflect}
137
const FloatLike{T<:AbstractFloat} = Union{T,AbstractGray{T}}
148
const FloatColorant{T<:AbstractFloat} = Colorant{T}
15-
@inline _default_fill(::Type{T}) where {T<:FloatLike} = convert(T, NaN)
16-
@inline _default_fill(::Type{T}) where {T<:FloatColorant} = _nan(T)
17-
@inline _default_fill(::Type{T}) where {T} = zero(T)
9+
@inline _default_fillvalue(::Type{T}) where {T<:FloatLike} = convert(T, NaN)
10+
@inline _default_fillvalue(::Type{T}) where {T<:FloatColorant} = _nan(T)
11+
@inline _default_fillvalue(::Type{T}) where {T} = zero(T)
1812

1913
@inline _make_compatible(T, fill) = fill
2014
@inline _make_compatible(::Type{T}, fill::Number) where {T} = T(fill)
2115

2216
Interpolations.tweight(A::AbstractArray{C}) where C<:Colorant{T} where T = T
2317

24-
box_extrapolation(etp::AbstractExtrapolation) = etp
25-
26-
function box_extrapolation(itp::AbstractInterpolation{T}, fill::FillType = _default_fill(T); kwargs...) where T
27-
etp = extrapolate(itp, _make_compatible(T, fill))
28-
box_extrapolation(etp)
29-
end
30-
31-
function box_extrapolation(parent::AbstractArray, args...; method::Union{Interpolations.Degree,Interpolations.InterpolationType}=Linear(), kwargs...)
32-
if typeof(method)<:Interpolations.Degree
33-
box_extrapolation(parent, method, args...)
34-
else
35-
itp = interpolate(parent, method)
36-
box_extrapolation(itp, args...)
37-
end
38-
end
39-
40-
function box_extrapolation(parent::AbstractArray{T,N}, degree::Interpolations.Degree, args...; method::Union{Interpolations.Degree,Interpolations.InterpolationType}=Linear(), kwargs...) where {T,N}
41-
itp = interpolate(parent, BSpline(degree))
42-
box_extrapolation(itp, args...)
43-
end
44-
45-
function box_extrapolation(parent::AbstractArray, degree::D, args...; method::Union{Interpolations.Degree,Interpolations.InterpolationType}=Linear(), kwargs...) where D<:Union{Linear,Constant}
46-
axs = axes(parent)
47-
T = typeof(zero(Interpolations.tweight(parent))*zero(eltype(parent)))
48-
itp = Interpolations.BSplineInterpolation{T,ndims(parent),typeof(parent),BSpline{D},typeof(axs)}(parent, axs, BSpline(degree))
49-
box_extrapolation(itp, args...)
50-
end
51-
52-
function box_extrapolation(parent::AbstractArray, fill::FillType; kwargs...)
53-
box_extrapolation(parent, Linear(), fill)
54-
end
55-
56-
function box_extrapolation(itp::AbstractInterpolation, degree::Union{Linear,Constant}, args...; kwargs...)
57-
throw(ArgumentError("Boxing an interpolation in another interpolation is discouraged. Did you specify the parameter \"$degree\" on purpose?"))
58-
end
18+
const MethodType = Union{Interpolations.Degree, Interpolations.InterpolationType}
5919

60-
function box_extrapolation(itp::AbstractInterpolation, degree::Interpolations.Degree, args...; kwargs...)
61-
throw(ArgumentError("Boxing an interpolation in another interpolation is discouraged. Did you specify the parameter \"$degree\" on purpose?"))
20+
function box_extrapolation(
21+
parent::AbstractArray;
22+
fillvalue::FillType = _default_fillvalue(eltype(parent)),
23+
method=Linear(),
24+
kwargs...)
25+
T = typeof(zero(Interpolations.tweight(parent)) * zero(eltype(parent)))
26+
itp = maybe_lazy_interpolate(T, parent, method)
27+
extrapolate(itp, _make_compatible(T, fillvalue))
6228
end
29+
box_extrapolation(etp::AbstractExtrapolation) = etp
30+
box_extrapolation(itp::AbstractInterpolation{T}; fillvalue=_default_fillvalue(T)) where T =
31+
extrapolate(itp, _make_compatible(T, fillvalue))
6332

64-
function box_extrapolation(itp::AbstractExtrapolation, fill::FillType; kwargs...)
65-
throw(ArgumentError("Boxing an extrapolation in another extrapolation is discouraged. Did you specify the parameter \"$fill\" on purpose?"))
33+
@inline function maybe_lazy_interpolate(::Type{T}, A::AbstractArray, degree::D) where {T, D<:Union{Linear, Constant}}
34+
axs = axes(A)
35+
return Interpolations.BSplineInterpolation{T,ndims(A),typeof(A),BSpline{D},typeof(axs)}(A, axs, BSpline(degree))
6636
end
6737

68-
function box_extrapolation(parent::AbstractArray, itp::Interpolations.InterpolationType; kwargs...)
69-
throw(ArgumentError("Argument support for interpolation is not supported. Are you looking for the method keyword to pass an interpolation method?"))
38+
@inline function maybe_lazy_interpolate(::Type{T}, A::AbstractArray, method::MethodType) where T
39+
return interpolate(A, wrap_BSpline(method))
7040
end
7141

7242
# This is type-piracy, but necessary if we want Interpolations to be

src/invwarpedview.jl

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct InvWarpedView{T,N,A,F,I,FI<:Transformation,E} <: AbstractArray{T,N}
2727
end
2828

2929
function InvWarpedView(inner::WarpedView{T,N,TA,F,I,E}) where {T,N,TA,F,I,E}
30-
tinv = inv(inner.transform)
30+
tinv = _round(inv(inner.transform))
3131
InvWarpedView{T,N,TA,F,I,typeof(tinv),E}(inner, tinv)
3232
end
3333

@@ -90,55 +90,20 @@ domain of the resulting `wv`. By default the indices are computed
9090
in such a way that `wv` contains all the original pixels in
9191
`img`.
9292
"""
93-
@inline invwarpedview(A::AbstractArray, tinv::Transformation, args...) =
94-
InvWarpedView(A, tinv, args...)
95-
96-
function invwarpedview(
97-
A::AbstractArray{T},
98-
tinv::Transformation,
99-
degree::Union{Linear,Constant},
100-
fill::FillType = _default_fill(T)) where T
101-
invwarpedview(box_extrapolation(A, degree, fill), tinv)
93+
function invwarpedview(A::AbstractArray, tinv::Transformation, indices::Tuple=autorange(A, tinv); kwargs...)
94+
InvWarpedView(box_extrapolation(A; kwargs...), tinv, indices)
10295
end
10396

104-
function invwarpedview(
105-
A::AbstractArray{T},
106-
tinv::Transformation,
107-
indices::Tuple,
108-
degree::Union{Linear,Constant},
109-
fill::FillType = _default_fill(T)) where T
110-
invwarpedview(box_extrapolation(A, degree, fill), tinv, indices)
97+
# For SubArray:
98+
# 1. We can exceed the boundary of SubArray by using its parent and thus trick Interpolations in
99+
# order to get better extrapolation result around the border. Otherwise it will just fill it.
100+
# 2. For default indices, we use `IdentityUnitRange`, which guarantees `r[i] == i`, to preserve the view indices.
101+
function invwarpedview(A::SubArray, tinv::Transformation; kwargs...)
102+
default_indices = map(IdentityUnitRange, autorange(CartesianIndices(A.indices), tinv))
103+
invwarpedview(A, tinv, default_indices; kwargs...)
111104
end
112-
113-
function invwarpedview(
114-
A::AbstractArray,
115-
tinv::Transformation,
116-
fill::FillType)
117-
invwarpedview(A, tinv, Linear(), fill)
118-
end
119-
120-
function invwarpedview(
121-
A::AbstractArray,
122-
tinv::Transformation,
123-
indices::Tuple,
124-
fill::FillType)
125-
invwarpedview(A, tinv, indices, Linear(), fill)
126-
end
127-
128-
function invwarpedview(
129-
inner_view::SubArray{T,N,W,I},
130-
tinv::Transformation) where {T,N,W<:InvWarpedView,I<:Tuple{Vararg{AbstractUnitRange}}}
131-
inner = parent(inner_view)
132-
new_inner = InvWarpedView(inner, tinv, autorange(inner, tinv))
133-
inds = autorange(CartesianIndices(inner_view.indices), tinv)
134-
view(new_inner, map(x->IdentityRange(first(x),last(x)), inds)...)
135-
end
136-
137-
function invwarpedview(
138-
inner_view::SubArray{T,N,W,I},
139-
tinv::Transformation,
140-
indices::Tuple) where {T,N,W<:InvWarpedView,I<:Tuple{Vararg{AbstractUnitRange}}}
141-
inner = parent(inner_view)
105+
function invwarpedview(A::SubArray, tinv::Transformation, indices::Tuple; kwargs...)
106+
inner = parent(A)
142107
new_inner = InvWarpedView(inner, tinv, autorange(inner, tinv))
143108
view(new_inner, indices...)
144109
end

0 commit comments

Comments
 (0)