From 1f698552b6d8980913be62511673453e2011b9dd Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 2 Jun 2021 08:42:52 +0200 Subject: [PATCH] `invokelatest` converts (#35) --- src/ImageIO.jl | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/ImageIO.jl b/src/ImageIO.jl index 31ade9f..0b3fad2 100644 --- a/src/ImageIO.jl +++ b/src/ImageIO.jl @@ -20,6 +20,22 @@ for FMT in ( end @inline canonical_type(::Formatted{T}, data) where T = canonical_type(T(), data) +function enforece_canonical_type(f, data) + AT = canonical_type(f, data) + # This may not be type stable if `AT` is not a concrete type, + # but it's not an issue for `load`; it can never be type stable. + + # work around the invokelatest overhead with an eager type check + if data isa AT + return data + else + # the backend might provide its own convert method + # use invokelatest to avoid world age issues + # See issue #34 + return Base.invokelatest(convert, AT, data) + end +end + ## PNGs const load_locker = Threads.ReentrantLock() @@ -33,11 +49,11 @@ end function load(f::File{DataFormat{:PNG}}; kwargs...) data = Base.invokelatest(checked_import(idPNGFiles).load, f.filename, kwargs...) - return convert(canonical_type(f, data), data) + return enforece_canonical_type(f, data) end function load(s::Stream{DataFormat{:PNG}}; kwargs...) data = Base.invokelatest(checked_import(idPNGFiles).load, stream(s), kwargs...) - return convert(canonical_type(s, data), data) + return enforece_canonical_type(s, data) end function save(f::File{DataFormat{:PNG}}, image::S; kwargs...) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}} @@ -60,12 +76,12 @@ for NETPBMFORMAT in (:PBMBinary, :PGMBinary, :PPMBinary, :PBMText, :PGMText, :PP @eval begin function load(f::File{DataFormat{$(Expr(:quote,NETPBMFORMAT))}}) data = Base.invokelatest(checked_import(idNetpbm).load, f) - return convert(canonical_type(f, data), data) + return enforece_canonical_type(f, data) end function load(s::Stream{DataFormat{$(Expr(:quote,NETPBMFORMAT))}}) data = Base.invokelatest(checked_import(idNetpbm).load, s) - return convert(canonical_type(s, data), data) + return enforece_canonical_type(s, data) end function save(f::File{DataFormat{$(Expr(:quote,NETPBMFORMAT))}}, image::S; kwargs...) where {S<:AbstractMatrix} @@ -82,11 +98,11 @@ end function load(f::File{DataFormat{:TIFF}}; kwargs...) data = Base.invokelatest(checked_import(idTiffImages).load, f.filename, kwargs...) - return convert(canonical_type(f, data), data) + return enforece_canonical_type(f, data) end function load(s::Stream{DataFormat{:TIFF}}; kwargs...) data = Base.invokelatest(checked_import(idTiffImages).load, stream(s), kwargs...) - return convert(canonical_type(s, data), data) + return enforece_canonical_type(s, data) end function save(f::File{DataFormat{:TIFF}}, image::S) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}}