Last active
December 9, 2019 19:46
-
-
Save SimonDanisch/016f7339177783b81961918c332703bf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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