Skip to content

Instantly share code, notes, and snippets.

@SimonDanisch
Last active December 9, 2019 19:46
Show Gist options
  • Save SimonDanisch/016f7339177783b81961918c332703bf to your computer and use it in GitHub Desktop.
Save SimonDanisch/016f7339177783b81961918c332703bf to your computer and use it in GitHub Desktop.
export play
"""
play(img, timedim, t)
Slice a 3D array along axis `timedim` at time `t`.
This can be used to treat a 3D array like a video and create an image stream from it.
"""
function play(array::Array{T, 3}, timedim::Integer, t::Integer) where T
index = ntuple(dim-> dim == timedim ? t : Colon(), Val(3))
array[index...]
end
"""
play(buffer, video_stream, t)
Plays a video stream from VideoIO.jl. You need to supply the image `buffer`,
which will be reused for better performance.
"""
function play(buffer::Array{T, 2}, video_stream, t) where T
eof(video_stream) && seekstart(video_stream)
w, h = size(buffer)
buffer = reinterpret(UInt8, buffer, (3, w,h))
read!(video_stream, buffer) # looses type and shape
return reinterpret(T, buffer, (w,h))
end
GLAbstraction.gl_convert(::Type{T}, img::AbstractArray) where {T} = _gl_convert(T, unwrap(img))
_gl_convert(::Type{T}, img::Array) where {T} = gl_convert(T, img)
unwrap(img::AbstractArray) = img
unwrap(img::AxisArrays.AxisArray) = unwrap(img.data)
"""
play(img)
Turns an Image into a video stream
"""
function play(img::HasAxesArray{T, 3}) where T
ax = ImageAxes.timeaxis(img)
if ImageAxes.timeaxis(img) != nothing
return const_lift(play, unwrap(img), ImageAxes.timedim(img), loop(1:length(ax)))
end
error("Image has no time axis: axes(img) = $(axes(img))")
end
"""
Takes a 3D image and decides if it is a volume or an animated Image.
"""
function _default(img::HasAxesArray{T, 3}, s::Style, data::Dict) where T
# We could do this as a @traitfn, except that those don't
# currently mix well with non-trait specialization.
if ImageAxes.timeaxis(img) != nothing
data[:spatialorder] = "yx"
td = ImageAxes.timedim(img)
video_signal = const_lift(play, unwrap(img), td, loop(1:size(img, timedim)))
return _default(video_signal, s, data)
else
ps = ImageAxes.pixelspacing(img)
spacing = Vec3f0(map(x-> x / maximum(ps), ps))
pdims = Vec3f0(map(length, indices(img)))
dims = pdims .* spacing
dims = dims/maximum(dims)
data[:dimensions] = dims
_default(unwrap(img), s, data)
end
end
function _default(img::TOrSignal{T}, s::Style, data::Dict) where T <: AxisMatrix
@gen_defaults! data begin
ranges = const_lift(img) do img
ps = ImageAxes.pixelspacing(img)
spacing = Vec2f0(map(x-> x / maximum(ps), ps))
pdims = Vec2f0(map(length, indices(img)))
dims = pdims .* spacing
dims = dims / maximum(dims)
(0:dims[1], 0:dims[2])
end
end
_default(const_lift(unwrap, img), s, data)
end
"""
Displays 3D array as movie with 3rd dimension as time dimension
"""
function _default(img::AbstractArray{T, 3}, s::Style, data::Dict) where T
video_signal = const_lift(play, unwrap(img), 3, loop(1:size(img, 3)))
return _default(video_signal, s, data)
end
function _default(main::IndirectArray{T}, s::Style, data::Dict) where T <: RGBA
@gen_defaults! data begin
volumedata = main.index => Texture
hull::GLUVWMesh = AABB{Float32}(Vec3f0(0), Vec3f0(1))
model = Mat4f0(I)
modelinv = const_lift(inv, model)
color_map = main.values => TextureBuffer
color_norm = nothing
color = nothing
algorithm = IndexedAbsorptionRGBA
shader = GLVisualizeShader("fragment_output.frag", "util.vert", "volume.vert", "volume.frag")
prerender = VolumePrerender()
postrender = () -> begin
glDisable(GL_CULL_FACE)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment