Skip to content

Commit

Permalink
fast path for uncompressed and uncomplicated images
Browse files Browse the repository at this point in the history
  • Loading branch information
chrstphrbrns committed Jan 11, 2024
1 parent 531eb14 commit d11435d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 29 deletions.
65 changes: 36 additions & 29 deletions src/ifds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,41 +281,48 @@ function Base.read!(target::AbstractArray{T, N}, tf::TiffFile{O, S}, ifd::IFD{O}
parallel_enabled = something(tryparse(Bool, get(ENV, "JULIA_IMAGES_PARALLEL", "1")), false)
do_parallel = parallel_enabled && rows * cols > 250_000 # pixels

tasks::Vector{Task} = []
start = 1
comp = Val(compression)
for (offset, len, bytes) in zip(offsets, strip_samples, encoded_bytes)
@debug "reading strip with $len samples from $bytes encoded bytes"

seek(tf, offset)
arr = view(samples, start:(start+len-1))
data = Vector{UInt8}(undef, bytes)
read!(tf, data)
tfs = TiffFileStrip{O}(IOBuffer(data), ifd)

function go(tfs, arr, comp)
cls = istiled(ifd) ? tilecols(ifd) : cols
cls = isplanar(ifd) ? cls : cls * spp # number of samples (not pixels) per column
rws = fld(length(arr), cls)
sz = uncompressed_size(ifd, cls, rws)
read!(tfs, view(reinterpret(UInt8, vec(arr)), 1:sz), comp)
if is_irregular_bps(ifd)
arr .= recode(arr, rws, cls, bps)
if is_complicated(ifd)
tasks::Vector{Task} = []
start = 1
for (offset, len, bytes) in zip(offsets, strip_samples, encoded_bytes)
@debug "reading strip with $len samples from $bytes encoded bytes"

seek(tf, offset)
arr = view(samples, start:(start+len-1))
data = Vector{UInt8}(undef, bytes)
read!(tf, data)
tfs = TiffFileStrip{O}(IOBuffer(data), ifd)

function go(tfs, arr, comp)
cls = istiled(ifd) ? tilecols(ifd) : cols
cls = isplanar(ifd) ? cls : cls * spp # number of samples (not pixels) per column
rws = fld(length(arr), cls)
sz = uncompressed_size(ifd, cls, rws)
read!(tfs, view(reinterpret(UInt8, vec(arr)), 1:sz), comp)
if is_irregular_bps(ifd)
arr .= recode(arr, rws, cls, bps)
end
reverse_prediction!(tfs.ifd, arr)
end
reverse_prediction!(tfs.ifd, arr)
end

if do_parallel
push!(tasks, Threads.@spawn go(tfs, arr, comp))
else
go(tfs, arr, comp)
if do_parallel
push!(tasks, Threads.@spawn go(tfs, arr, comp))
else
go(tfs, arr, comp)
end

start += len
end

start += len
end
for task in tasks
wait(task)
end
else
@debug "fast path for uncomplicated images"

for task in tasks
wait(task)
seek(tf, first(offsets))
read!(tf, target)
end

if isplanar(ifd)
Expand Down
2 changes: 2 additions & 0 deletions src/layout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ nsamples(ifd::IFD) = Int(getdata(ifd, SAMPLESPERPIXEL, 1))
predictor(ifd::IFD) = Int(getdata(ifd, PREDICTOR, 0))
bitspersample(ifd::IFD) = Int(first(ifd[BITSPERSAMPLE].data))::Int
ispalette(ifd::IFD) = Int(getdata(ifd, PHOTOMETRIC, 0)) == 3
compression(ifd::IFD) = getdata(CompressionType, ifd, COMPRESSION, COMPRESSION_NONE)

is_irregular_bps(ifd::IFD) = bitspersample(ifd) != sizeof(rawtype(ifd)) * 8
is_complicated(ifd::IFD) = !iscontiguous(ifd) || compression(ifd) != COMPRESSION_NONE || is_irregular_bps(ifd) == true || predictor(ifd) > 1

"""
interpretation(ifd)
Expand Down

0 comments on commit d11435d

Please sign in to comment.