diff --git a/src/Plots.jl b/src/Plots.jl index 65434b81..9b4bcb10 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -57,6 +57,7 @@ export savefig, png, gui, + inline, closeall, backend, diff --git a/src/animation.jl b/src/animation.jl index 1d2822f6..ee7428df 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -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, "\" />") + ext = file_extension(agif.filename) + write(io, if ext == "gif" + "\" />" + elseif ext in ("mov", "mp4") + "" + 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 diff --git a/src/output.jl b/src/output.jl index 0f4b01ae..ff4a1def 100644 --- a/src/output.jl +++ b/src/output.jl @@ -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( diff --git a/src/plot.jl b/src/plot.jl index 498135f6..2e8063af 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -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