animation fixes: show for videos, imagemagick init

This commit is contained in:
Tom Breloff 2016-12-01 10:23:41 -05:00
parent aa929ec24f
commit 4ed7144ca4

View File

@ -1,19 +1,19 @@
immutable Animation immutable Animation
dir::String dir::String
frames::Vector{String} frames::Vector{String}
end end
function Animation() function Animation()
tmpdir = convert(String, mktempdir()) tmpdir = convert(String, mktempdir())
Animation(tmpdir, String[]) Animation(tmpdir, String[])
end end
function frame{P<:AbstractPlot}(anim::Animation, plt::P=current()) function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
i = length(anim.frames) + 1 i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i) filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename)) png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename) push!(anim.frames, filename)
end end
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif") giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
@ -50,45 +50,60 @@ end
"Wraps the location of an animated gif so that it can be displayed" "Wraps the location of an animated gif so that it can be displayed"
immutable AnimatedGif immutable AnimatedGif
filename::String filename::String
end end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...) gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn; kw...) mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn; kw...) mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn; kw...)
const _imagemagick_initialized = Ref(false)
function buildanimation(animdir::AbstractString, fn::AbstractString; function buildanimation(animdir::AbstractString, fn::AbstractString;
fps::Integer = 20, loop::Integer = 0) fps::Integer = 20, loop::Integer = 0)
fn = abspath(fn) fn = abspath(fn)
try try
# high quality if !_imagemagick_initialized[]
speed = round(Int, 100 / fps) file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl")
file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl") if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH")
if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH") include(file)
include(file) end
_imagemagick_initialized[] = true
end
# prefix = get(ENV, "MAGICK_CONFIGURE_PATH", "")
# high quality
speed = round(Int, 100 / fps)
run(`convert -delay $speed -loop $loop $(joinpath(animdir, "*.png")) -alpha off $fn`)
catch err
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
Will try ffmpeg, but it's lower quality...)""")
# low quality
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -y $fn`)
# run(`ffmpeg -v warning -i "fps=$fps,scale=320:-1:flags=lanczos"`)
end end
# prefix = get(ENV, "MAGICK_CONFIGURE_PATH", "")
run(`convert -delay $speed -loop $loop $(joinpath(animdir, "*.png")) -alpha off $fn`)
catch err info("Saved animation to ", fn)
warn("""Tried to create gif using convert (ImageMagick), but got error: $err AnimatedGif(fn)
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
Will try ffmpeg, but it's lower quality...)""")
# low quality
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -y $fn`)
# run(`ffmpeg -v warning -i "fps=$fps,scale=320:-1:flags=lanczos"`)
end
info("Saved animation to ", fn)
AnimatedGif(fn)
end end
# write out html to view the gif... note the rand call which is a hack so the image doesn't get cached # write out html to view the gif... note the rand call which is a hack so the image doesn't get cached
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif) function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
write(io, "<img src=\"$(relpath(agif.filename))?$(rand())>\" />") ext = file_extension(agif.filename)
write(io, if ext == "gif"
"<img src=\"$(relpath(agif.filename))?$(rand())>\" />"
elseif ext in ("mov", "mp4")
"<video controls><source src=\"$(relpath(agif.filename))?$(rand())>\" type=\"video/$ext\"></video>"
else
error("Cannot show animation with extension $ext: $agif")
end)
end end
@ -154,7 +169,7 @@ Example:
``` ```
""" """
macro gif(forloop::Expr, args...) macro gif(forloop::Expr, args...)
_animate(forloop, args...; callgif = true) _animate(forloop, args...; callgif = true)
end end
""" """
@ -163,13 +178,13 @@ Collect one frame per for-block iteration and return an `Animation` object.
Example: Example:
``` ```
p = plot(1) p = plot(1)
anim = @animate for x=0:0.1:5 anim = @animate for x=0:0.1:5
push!(p, 1, sin(x)) push!(p, 1, sin(x))
end end
gif(anim) gif(anim)
``` ```
""" """
macro animate(forloop::Expr, args...) macro animate(forloop::Expr, args...)
_animate(forloop, args...) _animate(forloop, args...)
end end