Merge pull request #597 from tbreloff/dev

Output/Animation improvements
This commit is contained in:
Tom Breloff 2016-12-01 15:26:21 -05:00 committed by GitHub
commit d8ffd729f4
4 changed files with 72 additions and 43 deletions

View File

@ -57,6 +57,7 @@ export
savefig,
png,
gui,
inline,
closeall,
backend,

View File

@ -1,19 +1,19 @@
immutable Animation
dir::String
frames::Vector{String}
dir::String
frames::Vector{String}
end
function Animation()
tmpdir = convert(String, mktempdir())
Animation(tmpdir, String[])
tmpdir = convert(String, mktempdir())
Animation(tmpdir, String[])
end
function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename)
i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename)
end
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
@ -50,45 +50,60 @@ end
"Wraps the location of an animated gif so that it can be displayed"
immutable AnimatedGif
filename::String
filename::String
end
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
gif(anim::Animation, fn = giffn(); 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...)
const _imagemagick_initialized = Ref(false)
function buildanimation(animdir::AbstractString, fn::AbstractString;
fps::Integer = 20, loop::Integer = 0)
fn = abspath(fn)
try
# high quality
speed = round(Int, 100 / fps)
file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl")
if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH")
include(file)
fn = abspath(fn)
try
if !_imagemagick_initialized[]
file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl")
if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH")
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
# prefix = get(ENV, "MAGICK_CONFIGURE_PATH", "")
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
info("Saved animation to ", fn)
AnimatedGif(fn)
info("Saved animation to ", fn)
AnimatedGif(fn)
end
# 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)
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
@ -154,7 +169,7 @@ Example:
```
"""
macro gif(forloop::Expr, args...)
_animate(forloop, args...; callgif = true)
_animate(forloop, args...; callgif = true)
end
"""
@ -163,13 +178,13 @@ Collect one frame per for-block iteration and return an `Animation` object.
Example:
```
p = plot(1)
anim = @animate for x=0:0.1:5
p = plot(1)
anim = @animate for x=0:0.1:5
push!(p, 1, sin(x))
end
gif(anim)
end
gif(anim)
```
"""
macro animate(forloop::Expr, args...)
_animate(forloop, args...)
_animate(forloop, args...)
end

View File

@ -122,6 +122,13 @@ savefig(fn::AbstractString) = savefig(current(), fn)
gui(plt::Plot = current()) = display(PlotsDisplay(), plt)
# IJulia only... inline display
function inline(plt::Plot = current())
isijulia() || error("inline() is IJulia-only")
Main.IJulia.clear_output(true)
display(Main.IJulia.InlineDisplay(), plt)
end
function Base.display(::PlotsDisplay, plt::Plot)
prepare_output(plt)
_display(plt)
@ -130,6 +137,13 @@ end
# override the REPL display to open a gui window
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::Plot) = gui(plt)
_do_plot_show(plt, showval::Bool) = showval && gui(plt)
function _do_plot_show(plt, showval::Symbol)
showval == :gui && gui(plt)
showval in (:inline,:ijulia) && inline(plt)
end
# ---------------------------------------------------------
const _mimeformats = Dict(

View File

@ -126,9 +126,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# finish up
current(plt)
if get(d, :show, default(:show))
gui()
end
_do_plot_show(plt, get(d, :show, default(:show)))
plt
end
@ -234,9 +232,10 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
current(plt)
# do we want to force display?
if plt[:show]
gui(plt)
end
# if plt[:show]
# gui(plt)
# end
_do_plot_show(plt, plt[:show])
plt
end