1010
1111
1212"""
13- ScaleRatio(minlengths ) <: ProjectiveTransform
13+ ScaleRatio(ratios ) <: ProjectiveTransform
1414
1515Scales the aspect ratio
1616"""
1717struct ScaleRatio{N} <: ProjectiveTransform
1818 ratios:: NTuple{N}
1919end
2020
21+ # This allows for roundtrip through ScaleFixed and avoids code duplication
22+ fixed_sizes (scale:: ScaleRatio , bounds:: Bounds ) = round .(Int, scale. ratios .* length .(bounds. rs))
2123
22- function getprojection (scale:: ScaleRatio , bounds; randstate = nothing )
23- return scaleprojection (scale. ratios)
24+ function getprojection (scale:: ScaleRatio{N} , bounds:: Bounds{N} ; randstate = nothing ) where N
25+ return getprojection (ScaleFixed {N} (fixed_sizes (scale, bounds)), bounds; randstate)
26+ end
27+
28+ function projectionbounds (tfm:: ScaleRatio{N} , P, bounds:: Bounds{N} ; randstate = nothing ) where N
29+ projectionbounds (ScaleFixed {N} (fixed_sizes (tfm, bounds)), P, bounds; randstate)
2430end
2531
2632"""
2733 ScaleKeepAspect(minlengths) <: ProjectiveTransform
2834
29- Scales the shortest side of `item` to `minlengths`, keeping the
30- original aspect ratio.
35+ Scales the sides of `item` to be as least as large as `minlengths`,
36+ keeping the original aspect ratio.
3137
3238## Examples
3339
@@ -42,28 +48,15 @@ struct ScaleKeepAspect{N} <: ProjectiveTransform
4248 minlengths:: NTuple{N, Int}
4349end
4450
51+ # This allows for roundtrip through ScaleFixed and avoids code duplication
52+ fixed_sizes (scale:: ScaleKeepAspect , bounds:: Bounds ) = round .(Int, maximum (scale. minlengths ./ length .(bounds. rs)) .* length .(bounds. rs))
4553
4654function getprojection (scale:: ScaleKeepAspect{N} , bounds:: Bounds{N} ; randstate = nothing ) where N
47- # If no scaling needs to be done, return a noop transform
48- scale. minlengths == length .(bounds. rs) && return IdentityTransformation ()
49-
50- # Offset `minlengths` by 1 to avoid black border on one side
51- ratio = maximum ((scale. minlengths .+ 1 ) ./ length .(bounds. rs))
52- upperleft = SVector {N, Float32} (minimum .(bounds. rs)) .- 0.5
53- P = scaleprojection (Tuple (ratio for _ in 1 : N))
54- if any (upperleft .!= 0 )
55- P = P ∘ Translation ((Float32 .(P (upperleft)) .+ 0.5f0 ))
56- end
57- return P
55+ getprojection (ScaleFixed {N} (fixed_sizes (scale, bounds)), bounds; randstate)
5856end
5957
6058function projectionbounds (tfm:: ScaleKeepAspect{N} , P, bounds:: Bounds{N} ; randstate = nothing ) where N
61- origsz = length .(bounds. rs)
62- ratio = maximum ((tfm. minlengths) ./ origsz)
63- sz = round .(Int, ratio .* origsz)
64- bounds_ = transformbounds (bounds, P)
65- bs_ = offsetcropbounds (sz, bounds_, ntuple (_ -> 0.5 , N))
66- return bs_
59+ projectionbounds (ScaleFixed {N} (fixed_sizes (tfm, bounds)), P, bounds; randstate)
6760end
6861
6962"""
8073
8174
8275function getprojection (scale:: ScaleFixed , bounds:: Bounds{N} ; randstate = nothing ) where N
76+ # If no scaling needs to be done, return a noop transform
77+ (scale. sizes == length .(bounds. rs)) && return IdentityTransformation ()
78+
8379 ratios = (scale. sizes .+ 1 ) ./ length .(bounds. rs)
8480 upperleft = SVector {N, Float32} (minimum .(bounds. rs)) .- 1
8581 P = scaleprojection (ratios)
9288
9389function projectionbounds (tfm:: ScaleFixed{N} , P, bounds:: Bounds{N} ; randstate = nothing ) where N
9490 bounds_ = transformbounds (bounds, P)
95- return offsetcropbounds (tfm. sizes, bounds_, ntuple (_ -> 1. , N))
91+ return offsetcropbounds (tfm. sizes, bounds_, ntuple (_ -> 0.5 , N))
9692end
9793
9894"""
0 commit comments