Skip to content

Commit d89b877

Browse files
committed
Port autorange from ImageTransformations.jl 0.8
Changes made in JuliaImages/ImageTransformations.jl#143 lead to some output size changes after projective transformations that leave images with a black border. To revert to the pre 0.9 behavior, this ports the old `autorange`.
1 parent b57ae47 commit d89b877

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

src/projective/base.jl

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ end
4949
Apply `CoordinateTransformations.Transformation` to `bounds`.
5050
"""
5151
function transformbounds(bounds::Bounds, P::CoordinateTransformations.Transformation)
52-
return Bounds(ImageTransformations.autorange(CartesianIndices(bounds.rs), P))
52+
return Bounds(_autorange(CartesianIndices(bounds.rs), P))
5353
end
5454

5555
"""
@@ -129,3 +129,53 @@ struct Project{T<:CoordinateTransformations.Transformation} <: ProjectiveTransfo
129129
end
130130

131131
getprojection(tfm::Project, bounds; randstate = nothing) = tfm.P
132+
133+
# ## ImageTransformations.jl 0.8 internal functionality port
134+
#
135+
# Ported from ImageTransformations 0.8, since 0.9 introduced changes that broke
136+
# some assumptions.
137+
138+
function _autorange(img, tform)
139+
R = CartesianIndices(axes(img))
140+
autorange(R, tform)
141+
end
142+
143+
function _autorange(R::CartesianIndices, tform)
144+
tform = _round(tform)
145+
mn = mx = tform(SVector(first(R).I))
146+
for I in ImageTransformations.CornerIterator(R)
147+
x = tform(SVector(I.I))
148+
# we map min and max to prevent type-inference issues
149+
# (because min(::SVector,::SVector) -> Vector)
150+
mn = map(min, x, mn)
151+
mx = map(max, x, mx)
152+
end
153+
_autorange(Tuple(mn), Tuple(mx))
154+
end
155+
156+
@noinline _autorange(mn::Tuple, mx::Tuple) = map((a,b)->floor(Int,a):ceil(Int,b), mn, mx)
157+
158+
159+
# Slightly round/discretize the transformation so that the warpped image size isn't affected by
160+
# numerical stability
161+
# https://github.com/JuliaImages/ImageTransformations.jl/issues/104
162+
_default_digits(::Type{T}) where T<:Number = _default_digits(floattype(T))
163+
# these constants come from eps() digits
164+
_default_digits(::Type{<:AbstractFloat}) = 15
165+
_default_digits(::Type{Float64}) = 15
166+
_default_digits(::Type{Float32}) = 7
167+
168+
function _round(tform::T; kwargs...) where T<:CoordinateTransformations.Transformation
169+
rounded_fields = map(Base.OneTo(fieldcount(T))) do i
170+
__round(getfield(tform, i); kwargs...)
171+
end
172+
T(rounded_fields...)
173+
end
174+
if isdefined(Base, :ComposedFunction)
175+
_round(tform::ComposedFunction; kwargs...) = _round(tform.outer; kwargs...) _round(tform.inner; kwargs...)
176+
end
177+
_round(tform; kwargs...) = tform
178+
179+
__round(x; kwargs...) = x
180+
__round(x::AbstractArray; digits=_default_digits(eltype(x)), kwargs...) = round.(x; digits=digits, kwargs...)
181+
__round(x::T; digits=_default_digits(T), kwargs...) where T<:Number = round(x; digits=digits, kwargs...)

0 commit comments

Comments
 (0)