From 4fdd1ed9ce1307f52e28fb443b3a5feb26f112da Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 16 Jan 2021 15:39:27 -0600 Subject: [PATCH 1/4] Req CVS 0.9, eliminte deprecations --- Project.toml | 8 +- src/ImageCore.jl | 12 +-- src/colorchannels.jl | 12 +-- src/convert_reinterpret.jl | 1 - src/deprecations.jl | 68 ---------------- src/map.jl | 6 +- test/convert_reinterpret.jl | 150 +++++++++++++----------------------- test/deprecations.jl | 85 -------------------- test/runtests.jl | 6 +- 9 files changed, 72 insertions(+), 276 deletions(-) diff --git a/Project.toml b/Project.toml index 8501ed6..1f7417b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "ImageCore" uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" -version = "0.8.20" +version = "0.9.0" [deps] AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" +ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4" Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" Graphics = "a2bd30eb-e257-5431-a919-1863eab51364" @@ -15,8 +16,9 @@ Reexport = "189a3867-3050-52da-a836-e630ba90ab69" [compat] AbstractFFTs = "0.4, 0.5, 1.0" -Colors = "0.9, 0.10, 0.11, 0.12" -FixedPointNumbers = "0.6.1, 0.7, 0.8" +ColorVectorSpace = "0.9" +Colors = "0.12" +FixedPointNumbers = "0.8" Graphics = "0.4, 1.0" MappedArrays = "0.2, 0.3" MosaicViews = "0.2.3" diff --git a/src/ImageCore.jl b/src/ImageCore.jl index 300f8ce..00724fc 100644 --- a/src/ImageCore.jl +++ b/src/ImageCore.jl @@ -1,19 +1,9 @@ -VERSION < v"0.7.0-beta2.199" && __precompile__() - module ImageCore using Reexport @reexport using FixedPointNumbers @reexport using Colors -if isdefined(ColorTypes, :XRGB) && isdefined(ColorTypes, :RGB1) - Base.@deprecate_binding RGB1 XRGB - Base.@deprecate_binding RGB4 RGBX -end -# backward compatibility for ColorTypes < v0.9 -if !isdefined(ColorTypes, :XRGB) - const XRGB = RGB1 - const RGBX = RGB4 -end +using ColorVectorSpace @reexport using MosaicViews @reexport using PaddedViews diff --git a/src/colorchannels.jl b/src/colorchannels.jl index c530196..038fa39 100644 --- a/src/colorchannels.jl +++ b/src/colorchannels.jl @@ -121,12 +121,12 @@ _ccolorview(::Type{C}, A::RRArray{T,C}) where {C<:Colorant,T<:Number} = if VERSION >= v"1.6.0-DEV.1083" _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:RGB,T<:Number,M,AA} = reshape(parent(A), Base.tail(axes(parent(A)))) - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} = - parent(A) + # _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} = + # parent(A) _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:Color,T<:Number,M,AA} = reshape(parent(A), Base.tail(axes(parent(A)))) - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} = - parent(A) + # _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} = + # parent(A) else _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractGray,T<:Number,M} = parent(A) @@ -135,8 +135,8 @@ else _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:Color,T<:Number,M} = reshape(parent(A), Base.tail(axes(parent(A)))) end -_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractRGB,T<:Number,M} = - _colorview_reorder(C, A) +# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractRGB,T<:Number,M} = +# _colorview_reorder(C, A) _ccolorview(::Type{C}, A::AbstractArray{T}) where {C<:Colorant,T<:Number} = __ccolorview(C, A) # necessary to avoid ambiguities from dispatch on eltype __ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:RGB{T}} = reinterpretc(C, A) diff --git a/src/convert_reinterpret.jl b/src/convert_reinterpret.jl index 569bf8e..6ce1cde 100644 --- a/src/convert_reinterpret.jl +++ b/src/convert_reinterpret.jl @@ -83,7 +83,6 @@ for (fn,T) in (#(:float16, Float16), # Float16 currently has promotion problem ($fn)(::Type{S}) where {S<:Number } = $T ($fn)(c::Colorant) = convert(($fn)(typeof(c)), c) ($fn)(n::Number) = convert(($fn)(typeof(n)), n) - @deprecate ($fn)(A::AbstractArray{C}) where {C<:Colorant} ($fn).(A) fname = $(Expr(:quote, fn)) Tname = shortname($T) @doc """ diff --git a/src/deprecations.jl b/src/deprecations.jl index 119a118..e59a676 100644 --- a/src/deprecations.jl +++ b/src/deprecations.jl @@ -16,73 +16,5 @@ else forced_depwarn(msg, sym) = Base.depwarn(msg, sym) end -Base.@deprecate_binding ChannelView channelview - -export ColorView - -struct ColorView{C<:Colorant,N,A<:AbstractArray} <: AbstractArray{C,N} - parent::A - - function ColorView{C,N,A}(parent::AbstractArray{T}) where {C,N,A,T<:Number} - n = length(colorview_size(C, parent)) - n == N || throw(DimensionMismatch("for an $N-dimensional ColorView with color type $C, input dimensionality should be $n instead of $(ndims(parent))")) - checkdim1(C, axes(parent)) - forced_depwarn("ColorView{C}(A) is deprecated, use colorview(C, A)", :ColorView) - colorview(C, A) - end -end - -function ColorView{C}(A::AbstractArray) where C<:Colorant - forced_depwarn("ColorView{C}(A) is deprecated, use colorview(C, A)", :ColorView) - colorview(C, A) -end - -ColorView(parent::AbstractArray) = error("must specify the colortype, use colorview(C, A)") - -Base.@deprecate_binding squeeze1 true - -import Base: convert - -function cname(::Type{C}) where C - io = IOBuffer() - ColorTypes.colorant_string_with_eltype(io, C) - return String(take!(io)) -end - -const _explain = -"""will soon switch to returning an array with non-concrete element type, which adds flexibility but - with great cost to performance. To maintain the current behavior, use""" - -function convert(::Type{Array{Cdest}}, img::AbstractArray{Csrc,n}) where {Cdest<:Colorant,n,Csrc<:Colorant} - if isconcretetype(Cdest) - # This mimics the Base implementation - return img isa Array{Cdest} ? img : Array{Cdest}(img) - end - forced_depwarn("`convert(Array{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert) - convert(Array, Cdest.(img)) -end - -function convert(::Type{Array{Cdest}}, img::AbstractArray{T,n}) where {Cdest<:Color1,n,T<:Real} - if isconcretetype(Cdest) - return img isa Array{Cdest} ? img : Array{Cdest}(img) - end - forced_depwarn("`convert(Array{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert) - convert(Array, Cdest.(img)) -end - -function convert(::Type{OffsetArray{Cdest,n,A}}, img::AbstractArray{Csrc,n}) where {Cdest<:Colorant,n, A <:AbstractArray,Csrc<:Colorant} - if isconcretetype(Cdest) && isconcretetype(A) && eltype(A) === Cdest - return img isa OffsetArray{Cdest,n,A} ? img : (img isa OffsetArray ? OffsetArray(A(Cdest.(parent(img))), axes(img)) : OffsetArray(A(Cdest.(img)), axes(img))) - end - if img isa OffsetArray - forced_depwarn("`convert(OffsetArray{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert) - else - forced_depwarn("`convert(OffsetArray{$(cname(Cdest))}, img)` $_explain `OffsetArray($(cname(Cdest)).(img), axes(img))` instead.", :convert) - end - OffsetArray(Cdest.(img), axes(img)) -end - -convert(::Type{OffsetArray{Cdest,n,A}}, img::OffsetArray{Cdest,n,A}) where {Cdest<:Colorant,n, A <:AbstractArray} = img - # a perhaps "permanent" deprecation Base.@deprecate_binding permuteddimsview PermutedDimsArray diff --git a/src/map.jl b/src/map.jl index 846e39e..8ccd44f 100644 --- a/src/map.jl +++ b/src/map.jl @@ -210,9 +210,9 @@ See also: [`scalesigned`](@ref). """ colorsigned(neg::C, center::C, pos::C) where {C<:Colorant} = function(x) y = clamp(x, -oneunit(x), oneunit(x)) - yabs = abs(y) - C(ifelse(y>0, weighted_color_mean(yabs, pos, center), - weighted_color_mean(yabs, neg, center))) + yabs = norm(y) + C(ifelse(y>zero(y), weighted_color_mean(yabs, pos, center), + weighted_color_mean(yabs, neg, center))) end function colorsigned(colorneg::C, colorpos::C) where C<:Colorant diff --git a/test/convert_reinterpret.jl b/test/convert_reinterpret.jl index 0b96b06..652bd27 100644 --- a/test/convert_reinterpret.jl +++ b/test/convert_reinterpret.jl @@ -140,104 +140,6 @@ using Test, Random ret = @test_throws TypeError reinterpretc(Gray, a) end -@testset "Colorspace conversion" begin - a = [RGB(1,0,0) RGB(0,0,1); - RGB(0,1,0) RGB(1,1,1)] - c = @inferred(broadcast(BGR, a)) - @test eltype(c) == BGR{N0f8} - c = @inferred(broadcast(BGR{Float32}, a)) - @test eltype(c) == BGR{Float32} - c = @inferred(convert(Array{BGR{Float32}}, a)) # convert(Array{C}, a) where C is a concrete colortype is not deprecated - @test eltype(c) == BGR{Float32} - c = @inferred(broadcast(Lab, a)) - @test eltype(c) == Lab{Float32} - for a in (rand(Float32, (4,5)), - bitrand(4,5)) - b = @inferred(broadcast(Gray, a)) - @test eltype(b) == Gray{eltype(a)} - b = @inferred(broadcast(Gray{N0f8}, a)) - @test eltype(b) == Gray{N0f8} - b = @inferred(convert(Array{Gray{N0f8}}, a)) - @test eltype(b) == Gray{N0f8} - end - - # Gray images wrapped by an OffsetArray. - A = rand(8,8) - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(broadcast(Gray{Float32}, imgo)) - @test eltype(s) == Gray{Float32} - @test s isa OffsetArray{Gray{Float32},2,Array{Gray{Float32},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - s = @inferred(convert(OffsetArray{Gray{Float32},2,Array{Gray{Float32},2}},imgo)) - @test eltype(s) == Gray{Float32} - @test s isa OffsetArray{Gray{Float32},2,Array{Gray{Float32},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(broadcast(Gray{N0f8}, imgo)) - @test eltype(s) == Gray{N0f8} - @test s isa OffsetArray{Gray{N0f8},2,Array{Gray{N0f8},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(broadcast(Gray{N0f16}, imgo)) - @test eltype(s) == Gray{N0f16} - @test s isa OffsetArray{Gray{N0f16},2,Array{Gray{N0f16},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - # Color images wrapped by an OffsetArray. - A = rand(RGB{Float32},8,8) - for img in ( A, - n0f8.(A), - n6f10.(A), - n4f12.(A), - n2f14.(A), - n0f16.(A)) - imgo = OffsetArray(img, -2, -1) - s = @inferred(broadcast(RGB{N0f8}, imgo)) - @test eltype(s) == RGB{N0f8} - @test s isa OffsetArray{RGB{N0f8},2,Array{RGB{N0f8},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - s = @inferred(convert(OffsetArray{RGB{N0f8},2,Array{RGB{N0f8},2}},imgo)) - @test eltype(s) == RGB{N0f8} - @test s isa OffsetArray{RGB{N0f8},2,Array{RGB{N0f8},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - A = rand(RGB{Float32},8,8) - for img in ( A, - n0f8.(A), - n6f10.(A), - n4f12.(A), - n2f14.(A), - n0f16.(A)) - imgo = OffsetArray(img, -2, -1) - s = @inferred(broadcast(RGB{Float32}, imgo)) - @test eltype(s) == RGB{Float32} - @test s isa OffsetArray{RGB{Float32},2,Array{RGB{Float32},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end -end - @testset "eltype conversion" begin @test float32(Float64) == Float32 @test float32(N0f8) == Float32 @@ -302,6 +204,58 @@ end end end +@testset "convert and broadcasting" begin + a = [RGB(1,0,0) RGB(0,0,1); + RGB(0,1,0) RGB(1,1,1)] + c = @inferred(convert(Array{BGR}, a)) + @test eltype(c) === BGR + c = @inferred(convert(Array{BGR{Float32}}, a)) + @test eltype(c) === BGR{Float32} + c = @inferred(convert(Array{Lab}, a)) + @test eltype(c) === Lab + for a in (rand(Float32, (4,5)), + bitrand(4,5)) + b = @inferred(convert(Array{Gray}, a)) + @test eltype(b) === Gray + b = @inferred(convert(Array{Gray{N0f8}}, a)) + @test eltype(b) === Gray{N0f8} + end + + # Gray images wrapped by an OffsetArray. + A = rand(8,8) + for img in ( Gray.(A), + Gray.(N0f8.(A)), + Gray.(N0f16.(A)) ) + imgo = OffsetArray(img, -2, -1) + for T in (Gray{N0f8}, Gray{N0f16}, Gray{Float32}) + s = @inferred(broadcast(T, imgo)) + @test eltype(s) == T + @test s isa OffsetArray{T,2,Array{T,2}} + @test permutedims(permutedims(s,(2,1)),(2,1)) == s + @test axes(s) === axes(imgo) + end + end + + # Color images wrapped by an OffsetArray. + A = rand(RGB{Float32},8,8) + for img in ( A, + n0f8.(A), + n6f10.(A), + n4f12.(A), + n2f14.(A), + n0f16.(A)) + imgo = OffsetArray(img, -2, -1) + for T in (RGB{N0f8}, RGB{Float32}) + s = @inferred(broadcast(T, imgo)) + @test eltype(s) == T + @test s isa OffsetArray{T,2,Array{T,2}} + @test permutedims(permutedims(s,(2,1)),(2,1)) == s + @test axes(s) === axes(imgo) + end + end +end + + @testset "ambiguities" begin # issue #40 d = Dict(:a=>1, :b=>2.0) diff --git a/test/deprecations.jl b/test/deprecations.jl index 7da2a62..e77dd21 100644 --- a/test/deprecations.jl +++ b/test/deprecations.jl @@ -11,88 +11,3 @@ using Test, Random v = permuteddimsview(a, (2,3,1)) @test v == permutedims(a, (2,3,1)) end - -@testset "convert (deprecations)" begin - @info "Deprecation warnings are expected" - a = [RGB(1,0,0) RGB(0,0,1); - RGB(0,1,0) RGB(1,1,1)] - c = @inferred(convert(Array{BGR}, a)) - @test eltype(c) == BGR{N0f8} - c = @inferred(convert(Array{BGR{Float32}}, a)) - @test eltype(c) == BGR{Float32} - c = @inferred(convert(Array{Lab}, a)) - @test eltype(c) == Lab{Float32} - for a in (rand(Float32, (4,5)), - bitrand(4,5)) - b = @inferred(convert(Array{Gray}, a)) - @test eltype(b) == Gray{eltype(a)} - b = @inferred(convert(Array{Gray{N0f8}}, a)) - @test eltype(b) == Gray{N0f8} - end - - # Gray images wrapped by an OffsetArray. - A = rand(8,8) - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(convert(OffsetArray{Gray{Float32},2,Matrix{Gray{Float32}}},imgo)) - @test eltype(s) == Gray{Float32} - @test s isa OffsetArray{Gray{Float32},2,Array{Gray{Float32},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(convert(OffsetArray{Gray{N0f8},2,Matrix{Gray{N0f8}}},imgo)) - @test eltype(s) == Gray{N0f8} - @test s isa OffsetArray{Gray{N0f8},2,Array{Gray{N0f8},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - for img in ( Gray.(A), - Gray.(N0f8.(A)), - Gray.(N0f16.(A)) ) - imgo = OffsetArray(img, -2, -1) - s = @inferred(convert(OffsetArray{Gray{N0f16},2,Matrix{Gray{N0f16}}},imgo)) - @test eltype(s) == Gray{N0f16} - @test s isa OffsetArray{Gray{N0f16},2,Array{Gray{N0f16},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - # Color images wrapped by an OffsetArray. - A = rand(RGB{Float32},8,8) - for img in ( A, - n0f8.(A), - n6f10.(A), - n4f12.(A), - n2f14.(A), - n0f16.(A)) - imgo = OffsetArray(img, -2, -1) - s = @inferred(convert(OffsetArray{RGB{N0f8},2,Matrix{RGB{N0f8}}},imgo)) - @test eltype(s) == RGB{N0f8} - @test s isa OffsetArray{RGB{N0f8},2,Array{RGB{N0f8},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end - - A = rand(RGB{Float32},8,8) - for img in ( A, - n0f8.(A), - n6f10.(A), - n4f12.(A), - n2f14.(A), - n0f16.(A)) - imgo = OffsetArray(img, -2, -1) - s = @inferred(convert(OffsetArray{RGB{Float32},2,Matrix{RGB{Float32}}},imgo)) - @test eltype(s) == RGB{Float32} - @test s isa OffsetArray{RGB{Float32},2,Array{RGB{Float32},2}} - @test permutedims(permutedims(s,(2,1)),(2,1)) == s - @test axes(s) === axes(imgo) - end -end diff --git a/test/runtests.jl b/test/runtests.jl index 6c6361e..3e4bfbb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,7 +4,11 @@ using ImageCore, Test, ReferenceTests # If we've run the tests previously, there might be ambiguities from other packages if :StatsBase ∉ map(x->Symbol(string(x)), values(Base.loaded_modules)) - @test isempty(detect_ambiguities(ImageCore, Base, Core)) + if Base.VERSION < v"1.6.0-DEV.1005" + @test isempty(detect_ambiguities(ImageCore, Base, Core)) + else + @test isempty(detect_ambiguities(ImageCore)) + end end using Documenter From 16853d333f552811e531160b09b091001c05ea98 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 23 Jan 2021 08:22:23 -0600 Subject: [PATCH 2/4] Update dependencies, reduce latency Through better design and precompilation, this shaves about 30% off the time to run the tests. --- Project.toml | 4 +-- src/ImageCore.jl | 4 +++ src/colorchannels.jl | 2 +- src/precompile.jl | 86 ++++++++++++++++++++++++++++++++------------ src/stackedviews.jl | 6 ++-- test/benchmarks.jl | 12 +++---- test/map.jl | 4 +-- test/runtests.jl | 4 ++- test/traits.jl | 2 +- test/views.jl | 36 +++++++++---------- 10 files changed, 103 insertions(+), 57 deletions(-) diff --git a/Project.toml b/Project.toml index 1f7417b..ebf11b1 100644 --- a/Project.toml +++ b/Project.toml @@ -21,9 +21,9 @@ Colors = "0.12" FixedPointNumbers = "0.8" Graphics = "0.4, 1.0" MappedArrays = "0.2, 0.3" -MosaicViews = "0.2.3" +MosaicViews = "0.3.0" OffsetArrays = "0.8, 0.9, 0.10, 0.11, 1.0.1" -PaddedViews = "0.5.4" +PaddedViews = "0.5.8" Reexport = "0.2, 1.0" julia = "1" diff --git a/src/ImageCore.jl b/src/ImageCore.jl index 00724fc..c4c4364 100644 --- a/src/ImageCore.jl +++ b/src/ImageCore.jl @@ -164,6 +164,10 @@ function Base.transpose(a::AbstractVector{C}) where C<:Colorant out end +MosaicViews.promote_wrapped_type(::Type{T}, ::Type{S}) where {T<:Colorant,S<:Colorant} = promote_type(T, S) +MosaicViews.promote_wrapped_type(::Type{T}, ::Type{S}) where {T,S<:Colorant} = S === Union{} ? T : base_colorant_type(S){MosaicViews.promote_wrapped_type(T, eltype(S))} +MosaicViews.promote_wrapped_type(::Type{T}, ::Type{S}) where {T<:Colorant,S} = MosaicViews.promote_wrapped_type(S, T) + if VERSION >= v"1.4.2" # work around https://github.com/JuliaLang/julia/issues/34121 include("precompile.jl") _precompile_() diff --git a/src/colorchannels.jl b/src/colorchannels.jl index 038fa39..8f142e7 100644 --- a/src/colorchannels.jl +++ b/src/colorchannels.jl @@ -217,7 +217,7 @@ colorview(::Type{C}) where C<:Colorant = (As...) -> colorview(C, As...) _colorview_type(::Type{Any}, ::Type{T}) where {T} = T _colorview_type(::Type{T1}, ::Type{T2}) where {T1,T2} = T1 -Base.@pure promote_eleltype_all(gray, grays...) = _promote_eleltype_all(beltype(eltype(gray)), grays...) +Base.@pure @inline promote_eleltype_all(gray, grays...) = _promote_eleltype_all(beltype(eltype(gray)), grays...) @inline function _promote_eleltype_all(::Type{T}, gray, grays...) where T _promote_eleltype_all(promote_type(T, beltype(eltype(gray))), grays...) end diff --git a/src/precompile.jl b/src/precompile.jl index f0aac8e..a2836f8 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -1,9 +1,24 @@ +function pcarray(f::F, ::Type{A}, sz) where {F,A} + a = f(A(undef, sz)) + fill!(a, zero(eltype(a))) + return first(a) +end +function pcm(a1, a2; fillvalue = zero(eltype(a1))) + v = mosaic(a1, a2; fillvalue=fillvalue) + return first(v) +end +function pcmv(a; fillvalue = zero(eltype(a))) + v = mosaicview(a; fillvalue=fillvalue) + return first(v) +end + function _precompile_() ccall(:jl_generating_output, Cint, ()) == 1 || return nothing eltypes = (N0f8, N0f16, Float32, Float64) # eltypes of parametric colors pctypes = (Gray, RGB, AGray, GrayA, ARGB, RGBA) # parametric colors cctypes = (Gray24, AGray32, RGB24, ARGB32) # non-parametric colors dims = (1, 2, 3, 4) + szs = ((2,), (2, 2), (2, 2, 2), (2, 2, 2, 2)) for T in eltypes @assert precompile(clamp01, (T,)) @@ -21,38 +36,63 @@ function _precompile_() @assert precompile(clamp01, (C,)) @assert precompile(clamp01nan, (C,)) @assert precompile(colorsigned, (C,C)) -end - for n in dims + end + # For the arrays, it's better to make them and exercise them so we get the getindex/setindex! + # methods precompiled too. + for sz in szs for T in eltypes - @assert precompile(rawview, (Array{T,n},)) + T <: FixedPoint || continue + pcarray(rawview, Array{T,length(sz)}, sz) end - @assert precompile(normedview, (Array{UInt8,n},)) - @assert precompile(normedview, (Type{N0f8}, Array{UInt8,n})) - @assert precompile(normedview, (Type{N0f16}, Array{UInt16,n})) + pcarray(normedview, Array{UInt8,length(sz)}, sz) + pcarray(a->normedview(N0f8, a), Array{UInt8, length(sz)}, sz) + pcarray(a->normedview(N0f16, a), Array{UInt16,length(sz)}, sz) end - for T in eltypes - for n in dims + for sz in szs + for T in eltypes for C in pctypes - @assert precompile(colorview, (Type{C}, Array{T,n})) - @assert precompile(colorview, (Type{C{T}}, Array{T,n})) - if T<:FixedPoint - R = FixedPointNumbers.rawtype(T) - RA = Base.ReinterpretArray{T,n,R,Array{R,n}} - precompile(colorview, (Type{C}, RA)) - precompile(colorview, (Type{C{T}}, RA)) - precompile(reinterpretc, (Type{C{T}}, RA)) + nc = sizeof(C{T}) ÷ sizeof(T) + if nc == 1 + pcarray(a->colorview(C, a), Array{T,length(sz)}, sz) + pcarray(a->colorview(C{T}, a), Array{T,length(sz)}, sz) + else + pcarray(a->colorview(C, a), Array{T,length(sz)+1}, (nc, sz...)) + pcarray(a->colorview(C{T}, a), Array{T,length(sz)+1}, (nc, sz...)) end - @assert precompile(channelview, (Array{C{T},n},)) - end - for C in cctypes - @assert precompile(colorview, (Type{C}, Array{T,n})) + pcarray(channelview, Array{C{T},length(sz)}, sz) if T<:FixedPoint R = FixedPointNumbers.rawtype(T) - RA = Base.ReinterpretArray{T,n,R,Array{R,n}} - precompile(colorview, (Type{C}, RA)) + if nc == 1 + pcarray(a->colorview(C, normedview(T, a)), Array{R,length(sz)}, sz) + pcarray(a->colorview(C{T}, normedview(T, a)), Array{R,length(sz)}, sz) + else + pcarray(a->colorview(C, normedview(T, a)), Array{R,length(sz)+1}, (nc, sz...)) + pcarray(a->colorview(C{T}, normedview(T, a)), Array{R,length(sz)+1}, (nc, sz...)) + end end - @assert precompile(channelview, (Array{C,n},)) + end + end + T, C = Bool, Gray + pcarray(a->colorview(C, a), Array{T,length(sz)}, sz) + pcarray(a->colorview(C{T}, a), Array{T,length(sz)}, sz) + pcarray(channelview, Array{C{T},length(sz)}, sz) + end + for T in eltypes + a = zeros(T, (2, 2)) + a3 = zeros(T, (2, 2, 2)) + pcm(a, a) + pcmv(a3) + for C in (Gray, RGB, GrayA, RGBA) + a = zeros(C{T}, (2, 2)) + a3 = zeros(C{T}, (2, 2, 3)) + pcm(a, a) + pcmv(a3) + if C === RGB + pcm(a, a; fillvalue=zero(Gray{T})) + elseif C === RGBA + pcm(a, a; fillvalue=zero(GrayA{T})) end end end + pcm(zeros(Float32, 2, 2), zeros(Float64, 2, 2)) # heterogeneous end diff --git a/src/stackedviews.jl b/src/stackedviews.jl index 8e91ee1..b6abd6a 100644 --- a/src/stackedviews.jl +++ b/src/stackedviews.jl @@ -129,15 +129,15 @@ end # to use tuple tricks (i.e., make a tuple of length(inds)+1) _stackedview(T, (length(arrays), inds...), arrays_T) end -_stackedview(::Type{T}, ::Tuple{Vararg{Any,N}}, arrays) where {T,N} = StackedView{T,N,typeof(arrays)}(arrays) +@inline _stackedview(::Type{T}, ::Tuple{Vararg{Any,N}}, arrays) where {T,N} = StackedView{T,N,typeof(arrays)}(arrays) @inline firstinds(A::AbstractArray, Bs...) = axes(A) @inline firstinds(::ZeroArrayPromise, Bs...) = firstinds(Bs...) firstinds() = error("not all arrays can be zeroarray") -@inline take_zeros(T, inds, ::ZeroArrayPromise, Bs...) = (ZeroArrayPromise{T}(inds), take_zeros(T, inds, Bs...)...) -@inline take_zeros(T, inds, A::AbstractArray, Bs...) = (A, take_zeros(T, inds, Bs...)...) +@inline take_zeros(::Type{T}, inds, ::ZeroArrayPromise, Bs...) where T = (ZeroArrayPromise{T}(inds), take_zeros(T, inds, Bs...)...) +@inline take_zeros(::Type{T}, inds, A::AbstractArray, Bs...) where T = (A, take_zeros(T, inds, Bs...)...) take_zeros(T, inds) = () # Extensions of PaddedViews diff --git a/test/benchmarks.jl b/test/benchmarks.jl index a6d6042..dd32ceb 100644 --- a/test/benchmarks.jl +++ b/test/benchmarks.jl @@ -83,13 +83,13 @@ cc_setindex_funcs = (myfill1!, # Performance tolerances isfast = VERSION >= v"1.6.0-DEV.1083" -chanvtol = Dict(mysum_index_inbounds_simd => isfast ? 3 : 20, - mysum_elt_boundscheck => isfast ? 3 : 20, - myfill1! => 20, - myfill2! => isfast ? 3 : 20) +chanvtol = Dict{Any,Int}(mysum_index_inbounds_simd => isfast ? 3 : 20, + mysum_elt_boundscheck => isfast ? 3 : 20, + myfill1! => 20, + myfill2! => isfast ? 3 : 20) chanvdefault = isfast ? 3 : 10 -colvtol = Dict(mysum_elt_boundscheck=>isfast ? 3 : 5, - mysum_index_boundscheck=>isfast ? 3 : 5) +colvtol = Dict{Any,Int}(mysum_elt_boundscheck=>isfast ? 3 : 5, + mysum_index_boundscheck=>isfast ? 3 : 5) colvdefault = 3 ssz = (1000,300) diff --git a/test/map.jl b/test/map.jl index 56d75e7..c1696b8 100644 --- a/test/map.jl +++ b/test/map.jl @@ -20,7 +20,7 @@ using Test f = takemap(clamp01, A) fA = f.(A) @test eltype(fA) == Float64 - @test fA == [0, 0.4, 1] + @test fA == [0.0, 0.4, 1.0] f = takemap(clamp01, N0f8, A) fA = f.(A) @test eltype(fA) == N0f8 @@ -52,7 +52,7 @@ using Test f = takemap(clamp01nan, A) fA = f.(A) @test eltype(fA) == Float64 - @test fA == [0, 0.4, 0, 0, 1, 1] + @test fA == Float64[0, 0.4, 0, 0, 1, 1] f = takemap(clamp01nan, N0f8, A) fA = f.(A) @test eltype(fA) == N0f8 diff --git a/test/runtests.jl b/test/runtests.jl index 3e4bfbb..b9acc5b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,9 @@ using ImageCore, Test, ReferenceTests # If we've run the tests previously, there might be ambiguities from other packages if :StatsBase ∉ map(x->Symbol(string(x)), values(Base.loaded_modules)) if Base.VERSION < v"1.6.0-DEV.1005" - @test isempty(detect_ambiguities(ImageCore, Base, Core)) + ambs = detect_ambiguities(ImageCore, Base, Core) + ambs = filter(m1m2 -> ((m1, m2) = m1m2; m1.module === ImageCore || m2.module === ImageCore), ambs) + @test isempty(ambs) else @test isempty(detect_ambiguities(ImageCore)) end diff --git a/test/traits.jl b/test/traits.jl index 8847434..866af39 100644 --- a/test/traits.jl +++ b/test/traits.jl @@ -63,7 +63,7 @@ end @testset "GenericImage" begin @test GenericGrayImage <: GenericImage - for sz in [(3, 3), (3, 3, 3)] + for sz in Any[(3, 3), (3, 3, 3)] @test isa(rand(Bool, sz), GenericImage) @test isa(rand(N0f8, sz), GenericImage) @test isa(rand(Float32, sz), GenericImage) diff --git a/test/views.jl b/test/views.jl index f569d34..554480e 100644 --- a/test/views.jl +++ b/test/views.jl @@ -68,7 +68,7 @@ end @test size(V) == (3, 2, 2) @test axes(V) === (Base.OneTo(3), Base.OneTo(2), Base.OneTo(2)) @test V[1,:,:] == A - @test all(V[2,:,:] .== 0) + @test all(iszero, V[2,:,:]) @test V[3,:,:] == B @test_throws ErrorException V[2,1,1] = 7 V32 = @inferred(StackedView{Float32}(A, zeroarray, B)) @@ -186,21 +186,21 @@ end A1 = fill(Gray(1.), 2, 2) A2 = fill(RGB(1., 0., 0.), 3, 3) A3 = fill(RGB(0., 1., 0.), 3, 3) - out = mosaicview(A1, A2, A3) |> collect + out = mosaic(A1, A2, A3) |> collect @test_reference "references/mosaicviews/2d_opaque_1.png" out by=isequal - out = mosaicview(A1, A2, A3; npad=2, fillvalue=Gray(0.), nrow=2) |> collect + out = mosaic(A1, A2, A3; npad=2, fillvalue=Gray(0.), nrow=2) |> collect @test_reference "references/mosaicviews/2d_opaque_2.png" out by=isequal - out = mosaicview(A1, A2, A3; npad=2, fillvalue=Gray(0.), nrow=2, rowmajor=true) |> collect + out = mosaic(A1, A2, A3; npad=2, fillvalue=Gray(0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/2d_opaque_3.png" out by=isequal A1 = fill(GrayA(1.), 2, 2) A2 = fill(RGBA(1., 0., 0.), 3, 3) A3 = fill(RGBA(0., 1., 0.), 3, 3) - out = mosaicview(A1, A2, A3) |> collect + out = mosaic(A1, A2, A3) |> collect @test_reference "references/mosaicviews/2d_transparent_1.png" out by=isequal - out = mosaicview(A1, A2, A3; npad=2, fillvalue=GrayA(0., 0.), nrow=2) |> collect + out = mosaic(A1, A2, A3; npad=2, fillvalue=GrayA(0., 0.), nrow=2) |> collect @test_reference "references/mosaicviews/2d_transparent_2.png" out by=isequal - out = mosaicview(A1, A2, A3; npad=2, fillvalue=GrayA(0., 0.), nrow=2, rowmajor=true) |> collect + out = mosaic(A1, A2, A3; npad=2, fillvalue=GrayA(0., 0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/2d_transparent_3.png" out by=isequal end @@ -215,7 +215,7 @@ end @test_reference "references/mosaicviews/3d_opaque_2.png" out by=isequal out = mosaicview(A; npad=2, fillvalue=Gray(0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/3d_opaque_3.png" out by=isequal - out = mosaicview(A, A; npad=2, fillvalue=Gray(0.), nrow=2) |> collect + out = mosaic(A, A; npad=2, fillvalue=Gray(0.), nrow=2) |> collect @test_reference "references/mosaicviews/3d_opaque_4.png" out by=isequal A = fill(RGBA(0., 0., 0.), 2, 2, 3) @@ -228,7 +228,7 @@ end @test_reference "references/mosaicviews/3d_transparent_2.png" out by=isequal out = mosaicview(A; npad=2, fillvalue=GrayA(0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/3d_transparent_3.png" out by=isequal - out = mosaicview(A, A; npad=2, fillvalue=GrayA(0.), nrow=2) |> collect + out = mosaic(A, A; npad=2, fillvalue=GrayA(0.), nrow=2) |> collect @test_reference "references/mosaicviews/3d_transparent_4.png" out by=isequal end @@ -243,7 +243,7 @@ end @test_reference "references/mosaicviews/4d_opaque_2.png" out by=isequal out = mosaicview(A; npad=2, fillvalue=Gray(0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/4d_opaque_3.png" out by=isequal - out = mosaicview(A, A; npad=2, fillvalue=Gray(0.), nrow=2) |> collect + out = mosaic(A, A; npad=2, fillvalue=Gray(0.), nrow=2) |> collect @test_reference "references/mosaicviews/4d_opaque_4.png" out by=isequal A = fill(RGBA(0., 0., 0.), 2, 2, 2, 2) @@ -256,7 +256,7 @@ end @test_reference "references/mosaicviews/4d_transparent_2.png" out by=isequal out = mosaicview(A; npad=2, fillvalue=GrayA(0., 0.), nrow=2, rowmajor=true) |> collect @test_reference "references/mosaicviews/4d_transparent_3.png" out by=isequal - out = mosaicview(A, A; npad=2, fillvalue=GrayA(0.), nrow=2) |> collect + out = mosaic(A, A; npad=2, fillvalue=GrayA(0.), nrow=2) |> collect @test_reference "references/mosaicviews/4d_transparent_4.png" out by=isequal end end @@ -351,22 +351,22 @@ end @test Ap[axes(A)...] == ARGB{Float32}.(A) # order irrelevant - A = mosaicview(rand(Float32, 4, 4), rand(RGB{N0f8}, 4, 4)) + A = mosaic(rand(Float32, 4, 4), rand(RGB{N0f8}, 4, 4)) @test eltype(A) == RGB{Float32} - A = mosaicview(rand(RGB{N0f8}, 4, 4), rand(Float32, 4, 4)) + A = mosaic(rand(RGB{N0f8}, 4, 4), rand(Float32, 4, 4)) @test eltype(A) == RGB{Float32} - A = mosaicview(rand(Float32, 4, 4), rand(Gray{Float64}, 4, 4)) + A = mosaic(rand(Float32, 4, 4), rand(Gray{Float64}, 4, 4)) @test eltype(A) == Gray{Float64} - A = mosaicview(rand(Gray{Float64}, 4, 4), rand(Float32, 4, 4)) + A = mosaic(rand(Gray{Float64}, 4, 4), rand(Float32, 4, 4)) @test eltype(A) == Gray{Float64} - A = mosaicview(rand(Float32, 4, 4), rand(Gray{Float64}, 4, 4), rand(RGB{N0f8}, 4, 4)) + A = mosaic(rand(Float32, 4, 4), rand(Gray{Float64}, 4, 4), rand(RGB{N0f8}, 4, 4)) @test eltype(A) == RGB{Float64} - A = mosaicview(rand(Float32, 4, 4), rand(RGB{N0f8}, 4, 4), rand(Gray{Float64}, 4, 4)) + A = mosaic(rand(Float32, 4, 4), rand(RGB{N0f8}, 4, 4), rand(Gray{Float64}, 4, 4)) @test eltype(A) == RGB{Float64} - A = mosaicview(rand(Gray, 4, 4), rand(RGB, 4, 4)) + A = mosaic(rand(Gray, 4, 4), rand(RGB, 4, 4)) @test eltype(A) == RGB{Float64} # the filltype is always a concrete type end From 62b56174b6b2b51e960115e82ee12326f0e0df30 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 4 Mar 2021 10:01:20 -0600 Subject: [PATCH 3/4] Warn, don't error, on precompile failures --- src/precompile.jl | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/precompile.jl b/src/precompile.jl index a2836f8..382bac8 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -1,3 +1,14 @@ +macro warnpcfail(ex::Expr) + modl = __module__ + file = __source__.file === nothing ? "?" : String(__source__.file) + line = __source__.line + quote + $(esc(ex)) || @warn """precompile directive + $($(Expr(:quote, ex))) + failed. Please report an issue in $($modl) (after checking for duplicates) or remove this directive.""" _file=$file _line=$line + end +end + function pcarray(f::F, ::Type{A}, sz) where {F,A} a = f(A(undef, sz)) fill!(a, zero(eltype(a))) @@ -21,21 +32,21 @@ function _precompile_() szs = ((2,), (2, 2), (2, 2, 2), (2, 2, 2, 2)) for T in eltypes - @assert precompile(clamp01, (T,)) - @assert precompile(clamp01nan, (T,)) - @assert precompile(scaleminmax, (T, T)) - @assert precompile(scalesigned, (T,)) - @assert precompile(scalesigned, (T,T,T)) + @warnpcfail precompile(clamp01, (T,)) + @warnpcfail precompile(clamp01nan, (T,)) + @warnpcfail precompile(scaleminmax, (T, T)) + @warnpcfail precompile(scalesigned, (T,)) + @warnpcfail precompile(scalesigned, (T,T,T)) for C in pctypes - @assert precompile(clamp01, (C{T},)) - @assert precompile(clamp01nan, (C{T},)) - @assert precompile(colorsigned, (C{T},C{T})) + @warnpcfail precompile(clamp01, (C{T},)) + @warnpcfail precompile(clamp01nan, (C{T},)) + @warnpcfail precompile(colorsigned, (C{T},C{T})) end end for C in cctypes - @assert precompile(clamp01, (C,)) - @assert precompile(clamp01nan, (C,)) - @assert precompile(colorsigned, (C,C)) + @warnpcfail precompile(clamp01, (C,)) + @warnpcfail precompile(clamp01nan, (C,)) + @warnpcfail precompile(colorsigned, (C,C)) end # For the arrays, it's better to make them and exercise them so we get the getindex/setindex! # methods precompiled too. From 6f6b4ae46b17e7634cab450f6049e99cb766c6d3 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 21 Apr 2021 20:46:00 +0800 Subject: [PATCH 4/4] reexport ColorVectorSpace --- src/ImageCore.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageCore.jl b/src/ImageCore.jl index 4f46f3f..f835c9c 100644 --- a/src/ImageCore.jl +++ b/src/ImageCore.jl @@ -3,7 +3,7 @@ module ImageCore using Reexport @reexport using FixedPointNumbers @reexport using Colors -using ColorVectorSpace +@reexport using ColorVectorSpace @reexport using MosaicViews @reexport using PaddedViews