Skip to content

Commit

Permalink
Don't rely on FileIO internals (#22)
Browse files Browse the repository at this point in the history
This should be faster and it is necessary for an uncoming
rewrite of FileIO.
  • Loading branch information
timholy authored Mar 1, 2021
1 parent dfe848b commit 3171a61
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 43 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
Netpbm = "f09324ee-3d7c-5217-9330-fc30815ba969"
PNGFiles = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883"
TiffImages = "731e570b-9d59-4bfa-96dc-6df516fadf69"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
FileIO = "1.2"
Expand Down
62 changes: 19 additions & 43 deletions src/ImageIO.jl
Original file line number Diff line number Diff line change
@@ -1,46 +1,32 @@
module ImageIO

using FileIO: File, DataFormat, Stream, stream, _findmod, topimport
using UUIDs
using FileIO: File, DataFormat, Stream, stream

const load_locker = Base.ReentrantLock()

function checked_import(pkg::Symbol)
lock(load_locker) do
if isdefined(ImageIO, pkg)
m1 = getfield(ImageIO, pkg)
isa(m1, Module) && return m1
end
if isdefined(Main, pkg)
m1 = getfield(Main, pkg)
isa(m1, Module) && return m1
end
m = _findmod(pkg)
m == nothing || return Base.loaded_modules[m]
@eval ImageIO import $pkg
return Base.getfield(ImageIO, pkg)
end
end
const idNetpbm = Base.PkgId(UUID("f09324ee-3d7c-5217-9330-fc30815ba969"), "Netpbm")
const idPNGFiles = Base.PkgId(UUID("f57f5aa1-a3ce-4bc8-8ab9-96f992907883"), "PNGFiles")
const idTiffImages = Base.PkgId(UUID("731e570b-9d59-4bfa-96dc-6df516fadf69"), "TiffImages")

## PNGs

function load(f::File{DataFormat{:PNG}}; kwargs...)
return Base.invokelatest(checked_import(:PNGFiles).load, f.filename, kwargs...)
return Base.invokelatest(Base.require(idPNGFiles).load, f.filename, kwargs...)
end
function load(s::Stream{DataFormat{:PNG}}; kwargs...)
return Base.invokelatest(checked_import(:PNGFiles).load, stream(s), kwargs...)
return Base.invokelatest(Base.require(idPNGFiles).load, stream(s), kwargs...)
end

function save(f::File{DataFormat{:PNG}}, image::S; kwargs...) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}}
return Base.invokelatest(checked_import(:PNGFiles).save, f.filename, image, kwargs...)
return Base.invokelatest(Base.require(idPNGFiles).save, f.filename, image, kwargs...)
end

function save(s::Stream{DataFormat{:PNG}}, image::S; permute_horizontal=false, mapi=identity, kwargs...) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}}
imgout = map(mapi, image)
if permute_horizontal
perm = ndims(imgout) == 2 ? (2, 1) : ndims(imgout) == 3 ? (2, 1, 3) : error("$(ndims(imgout)) dims array is not supported")
return Base.invokelatest(checked_import(:PNGFiles).save, stream(s), PermutedDimsArray(imgout, perm), kwargs...)
return Base.invokelatest(Base.require(idPNGFiles).save, stream(s), PermutedDimsArray(imgout, perm), kwargs...)
else
return Base.invokelatest(checked_import(:PNGFiles).save, stream(s), imgout, kwargs...)
return Base.invokelatest(Base.require(idPNGFiles).save, stream(s), imgout, kwargs...)
end
end

Expand All @@ -49,58 +35,48 @@ end
for NETPBMFORMAT in (:PBMBinary, :PGMBinary, :PPMBinary, :PBMText, :PGMText, :PPMText)
@eval begin
function load(f::File{DataFormat{$(Expr(:quote,NETPBMFORMAT))}})
return Base.invokelatest(checked_import(:Netpbm).load, f)
return Base.invokelatest(Base.require(idNetpbm).load, f)
end

function load(s::Stream{DataFormat{$(Expr(:quote,NETPBMFORMAT))}})
return Base.invokelatest(checked_import(:Netpbm).load, s)
return Base.invokelatest(Base.require(idNetpbm).load, s)
end

function save(f::File{DataFormat{$(Expr(:quote,NETPBMFORMAT))}}, image::S; kwargs...) where {S<:AbstractMatrix}
return Base.invokelatest(checked_import(:Netpbm).save, f, image; kwargs...)
return Base.invokelatest(Base.require(idNetpbm).save, f, image; kwargs...)
end

function save(s::Stream{DataFormat{$(Expr(:quote,NETPBMFORMAT))}}, image::S; kwargs...) where {S<:AbstractMatrix}
return Base.invokelatest(checked_import(:Netpbm).save, s, image; kwargs...)
return Base.invokelatest(Base.require(idNetpbm).save, s, image; kwargs...)
end
end
end

## TIFFs

function load(f::File{DataFormat{:TIFF}}; kwargs...)
return Base.invokelatest(checked_import(:TiffImages).load, f.filename, kwargs...)
return Base.invokelatest(Base.require(idTiffImages).load, f.filename, kwargs...)
end
function load(s::Stream{DataFormat{:TIFF}}; kwargs...)
return Base.invokelatest(checked_import(:TiffImages).load, stream(s), kwargs...)
return Base.invokelatest(Base.require(idTiffImages).load, stream(s), kwargs...)
end

function save(f::File{DataFormat{:TIFF}}, image::S) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}}
Base.invokelatest(checked_import(:TiffImages).save, f.filename, image)
Base.invokelatest(Base.require(idTiffImages).save, f.filename, image)
end

function save(s::Stream{DataFormat{:TIFF}}, image::S; permute_horizontal=false, mapi=identity) where {T, S<:Union{AbstractMatrix, AbstractArray{T,3}}}
imgout = map(mapi, image)
if permute_horizontal
perm = ndims(imgout) == 2 ? (2, 1) : ndims(imgout) == 3 ? (2, 1, 3) : error("$(ndims(imgout)) dims array is not supported")
Base.invokelatest(checked_import(:TiffImages).save, stream(s), PermutedDimsArray(imgout, perm))
Base.invokelatest(Base.require(idTiffImages).save, stream(s), PermutedDimsArray(imgout, perm))
else
Base.invokelatest(checked_import(:TiffImages).save, stream(s), imgout)
Base.invokelatest(Base.require(idTiffImages).save, stream(s), imgout)
end
end

## Function names labelled for FileIO. Makes FileIO lookup quicker
const fileio_save = save
const fileio_load = load

## Precompiles
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
@assert Base.precompile(Tuple{typeof(checked_import),Symbol})
end

if Base.VERSION >= v"1.5"
_precompile_()
end

end # module

0 comments on commit 3171a61

Please sign in to comment.