Giter Site home page Giter Site logo

Comments (13)

Wikunia avatar Wikunia commented on June 5, 2024 2

Currently svg isn't directly supported but simply because we didn't find a good way to make use of it in animations. It would be fairly simple though to render the single images as svgs as it's supported by Luxor. You can search for PNG inside Javis and replace it with SVG. That should be all there is to it if you are only interested in the single frames in the temporary directory

from javis.jl.

ArbitRandomUser avatar ArbitRandomUser commented on June 5, 2024 1

Currently svg isn't directly supported but simply because we didn't find a good way to make use of it in animations. It would be fairly simple though to render the single images as svgs as it's supported by Luxor. You can search for PNG inside Javis and replace it with SVG. That should be all there is to it if you are only interested in the single frames in the temporary directory

Simply changing to .png might not quite work like how they want exactly ...right ? , by the time we call Image.save to save it to tempdir we have already rasterized the image into frame_image, i dont know if Image.save will convert it back to svg , but even if it does you wont get the original vector image as you would have got if Luxor wrote the svg.

from javis.jl.

gpucce avatar gpucce commented on June 5, 2024

Hi @aburousan changing

act!(circles[i], Action(1:1, anim_translate(circles[i-1])))

with

act!(circles[i], Action(1:1, anim_translate(O, circles[i-1])))

Should fix the error, could you check if it does?

from javis.jl.

aburousan avatar aburousan commented on June 5, 2024

It's rendering but now it's showing new error

E:\>julia fourier.jl
#points: 643
TSP cost: 1851.3679707085373
Rendering frames...100%|████████████████████████████████████████████████████████████████████████| Time: 0:00:28
ERROR: LoadError: failed process: Process(`'C:\Users\Syeda Spandita Zaman\.julia\artifacts\ecb81e6429c089c1da802644fae337754832d534\bin\ffmpeg.exe' -loglevel panic -framerate 30 -i 'C:\Users\SYEDAS~1\AppData\Local\Temp\jl_t5RcVi/%10d.png' -i 'C:\Users\SYEDAS~1\AppData\Local\Temp\jl_t5RcVi/palette.png' -lavfi paletteuse -y 'E:\gifs/julia_logo_dft.gif'`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ .\process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base .\process.jl:446
  [3] run
    @ .\process.jl:444 [inlined]
  [4] (::FFMPEG.var"#4#6"{Cmd})(command_path::String)
    @ FFMPEG C:\Users\Syeda Spandita Zaman\.julia\packages\FFMPEG\OUpap\src\FFMPEG.jl:112
  [5] (::JLLWrappers.var"#2#3"{FFMPEG.var"#4#6"{Cmd}, String})()
    @ JLLWrappers C:\Users\Syeda Spandita Zaman\.julia\packages\JLLWrappers\QpMQW\src\runtime.jl:49
  [6] withenv(f::JLLWrappers.var"#2#3"{FFMPEG.var"#4#6"{Cmd}, String}, keyvals::Pair{String, String})
    @ Base .\env.jl:172
  [7] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers C:\Users\Syeda Spandita Zaman\.julia\packages\JLLWrappers\QpMQW\src\runtime.jl:48
  [8] #invokelatest#2
    @ .\essentials.jl:716 [inlined]
  [9] invokelatest
    @ .\essentials.jl:714 [inlined]
 [10] #ffmpeg#3
    @ C:\Users\Syeda Spandita Zaman\.julia\packages\JLLWrappers\QpMQW\src\products\executable_generators.jl:21 [inlined]
 [11] ffmpeg
    @ C:\Users\Syeda Spandita Zaman\.julia\packages\JLLWrappers\QpMQW\src\products\executable_generators.jl:21 [inlined]
 [12] #exe#2
    @ C:\Users\Syeda Spandita Zaman\.julia\packages\FFMPEG\OUpap\src\FFMPEG.jl:111 [inlined]
 [13] ffmpeg_exe
    @ C:\Users\Syeda Spandita Zaman\.julia\packages\FFMPEG\OUpap\src\FFMPEG.jl:123 [inlined]
 [14] render(video::Video; framerate::Int64, pathname::String, liveview::Bool, streamconfig::Nothing, tempdirectory::String, ffmpeg_loglevel::String, rescale_factor::Float64, postprocess_frames_flow::typeof(identity), postprocess_frame::typeof(Javis.default_postprocess))
    @ Javis C:\Users\Syeda Spandita Zaman\.julia\packages\Javis\TCcr1\src\Javis.jl:350
 [15] animate_fourier(options::NamedTuple{(:npoints, :nplay_frames, :nruns, :nend_frames, :width, :height, :shape_scale, :tsp_quality_factor, :filename), Tuple{Int64, Int64, Int64, Int64, Int64, Int64, Float64, Int64, String}})
    @ Main E:\\fourier.jl:146
 [16] main()
    @ Main E:\\fourier.jl:185
 [17] top-level scope
    @ E:\\fourier.jl:188
in expression starting at E:\fourier.jl:188

from javis.jl.

gpucce avatar gpucce commented on June 5, 2024

Hi, this I believe might depend on the pathname you used but I can't find this out without seeing your code.

Could you share the exact code you use?

from javis.jl.

Wikunia avatar Wikunia commented on June 5, 2024

Basically the last line with render as I assume everything else is from our Fourier example.

from javis.jl.

aburousan avatar aburousan commented on June 5, 2024

This is the code

using Javis, FFTW, FFTViews
using TravelingSalesmanHeuristics

function ground(args...)
    background("black")
    sethue("white")
end

function circ(; r = 10, vec = O, action = :stroke, color = "white")
    sethue(color)
    circle(O, r, action)
    my_arrow(O, vec)
    return vec
end

function my_arrow(start_pos, end_pos)
    arrow(
        start_pos,
        end_pos;
        linewidth = distance(start_pos, end_pos) / 100,
        arrowheadlength = 7,
    )
    return end_pos
end

function draw_line(
    p1 = O,
    p2 = O;
    color = "white",
    action = :stroke,
    edge = "solid",
    linewidth = 3,
)
    sethue(color)
    setdash(edge)
    setline(linewidth)
    line(p1, p2, action)
end

function draw_path!(path, pos, color)
    sethue(color)

    push!(path, pos)
    return draw_line.(path[2:end], path[1:(end - 1)]; color = color)
end

function get_points(npoints, options)
    Drawing() # julialogo needs a drawing
    julialogo(; action = :path, centered = true)
    shapes = pathtopoly()
    new_shapes = shapes[1:6]
    last_i = 1
    # the circles in the JuliaLogo are part of a single shape
    # this loop creates new shapes for each circle
    for shape in shapes[7:7]
        max_dist = 0.0
        for i in 2:length(shape)
            d = distance(shape[i - 1], shape[i])
            if d > 3
                push!(new_shapes, shape[last_i:(i - 1)])
                last_i = i
            end
        end
    end
    push!(new_shapes, shapes[7][last_i:end])
    shapes = new_shapes
    for i in 1:length(shapes)
        shapes[i] .*= options.shape_scale
    end

    total_distance = 0.0
    for shape in shapes
        total_distance += polyperimeter(shape)
    end
    parts = []
    points = Point[]
    start_i = 1
    for shape in shapes
        len = polyperimeter(shape)
        portion = len / total_distance
        nlocalpoints = floor(Int, portion * npoints)
        new_points = [
            Javis.get_polypoint_at(shape, i / (nlocalpoints - 1)) for
            i in 0:(nlocalpoints - 1)
        ]
        append!(points, new_points)
        new_i = start_i + length(new_points) - 1
        push!(parts, start_i:new_i)
        start_i = new_i
    end
    return points, parts
end

c2p(c::Complex) = Point(real(c), imag(c))

remap_idx(i::Int) = (-1)^i * floor(Int, i / 2)
remap_inv(n::Int) = 2n * sign(n) - 1 * (n > 0)

function animate_fourier(options)
    npoints = options.npoints
    nplay_frames = options.nplay_frames
    nruns = options.nruns
    nframes = nplay_frames + options.nend_frames

    # obtain points from julialogo
    points, parts = get_points(npoints, options)
    npoints = length(points)
    println("#points: $npoints")
    # solve tsp to reduce length of extra edges
    distmat = [distance(points[i], points[j]) for i in 1:npoints, j in 1:npoints]

    path, cost = solve_tsp(distmat; quality_factor = options.tsp_quality_factor)
    println("TSP cost: $cost")
    points = points[path] # tsp saves the last point again

    # optain the fft result and scale
    x = [p.x for p in points]
    y = [p.y for p in points]

    fs = FFTView(fft(complex.(x, y)))
    # normalize the points as fs isn't normalized
    fs ./= npoints
    npoints = length(fs)

    video = Video(options.width, options.height)
    Background(1:nframes, ground)

    circles = Object[]

    for i in 1:npoints
        ridx = remap_idx(i)

        push!(circles, Object((args...) -> circ(; r = abs(fs[ridx]), vec = c2p(fs[ridx]))))

        if i > 1
            # translate to the tip of the vector of the previous circle
            act!(circles[i], Action(1:1, anim_translate(O, circles[i-1])))
        end
        ridx = remap_idx(i)
        act!(circles[i], Action(1:nplay_frames, anim_rotate(0.0, ridx * 2π * nruns)))
    end

    trace_points = Point[]
    Object(1:nframes, (args...) -> draw_path!(trace_points, pos(circles[end]), "red"))

    return render(video; pathname = joinpath(@__DIR__, options.filename))
end

function main()
    hd_options = (
        npoints = 3001, # rough number of points for the shape => number of circles
        nplay_frames = 1200, # number of frames for the animation of fourier
        nruns = 2, # how often it's drawn
        nend_frames = 200,  # number of frames in the end
        width = 1920,
        height = 1080,
        shape_scale = 2.5, # scale factor for the logo
        tsp_quality_factor = 50,
        filename = "julia_hd.mp4",
    )

    fast_options = (
        npoints = 1001, # rough number of points for the shape => number of circles
        nplay_frames = 600, # number of frames for the animation of fourier
        nruns = 1, # how often it's drawn
        nend_frames = 200,  # number of frames in the end
        width = 1000,
        height = 768,
        shape_scale = 1.5, # scale factor for the logo
        tsp_quality_factor = 40,
        filename = "julia_fast.mp4",
    )

    gif_options = (
        npoints = 651, # rough number of points for the shape => number of circles
        nplay_frames = 600, # number of frames for the animation of fourier
        nruns = 2, # how often it's drawn
        nend_frames = 0,  # number of frames in the end
        width = 350,
        height = 219,
        shape_scale = 0.8, # scale factor for the logo
        tsp_quality_factor = 80,
        filename = "gifs/julia_logo_dft.gif",
    )
    return animate_fourier(gif_options)
end

main()

from javis.jl.

gpucce avatar gpucce commented on June 5, 2024

Hi, you need to change this line:

return render(video; pathname = joinpath(@__DIR__, options.filename))

with something like

return render(video; pathname = "path2gif.gif")

Can you tell if this does it?

from javis.jl.

aburousan avatar aburousan commented on June 5, 2024

Thanks ... Now it's working like a charm...
If you don't mind, I have another question.
How can we save a particular frame of the animation as svg? And how can we make a Fourier plot for any random word(text)?

from javis.jl.

ArbitRandomUser avatar ArbitRandomUser commented on June 5, 2024

running `render(video,tempdirecory='moviedir',pathname="") will save each frame as .png in moviedir

as of now there is seems to be no way to get svg of a frame from render , the frame is returned rasterized for render to stitch it.
(someone who knows the innards of Javis better than me plis confirm)

from javis.jl.

gpucce avatar gpucce commented on June 5, 2024

Hi, I also don't think it is possible right away, perhaps playing a bit with Javis code.

@aburousan would like to try and open a PR to fix the example? If you don't no worries I will do it! :)

from javis.jl.

aburousan avatar aburousan commented on June 5, 2024

Sure

from javis.jl.

Wikunia avatar Wikunia commented on June 5, 2024

Ah you're right I think before we added layer functionality this was actually as simple as I described but now it would be a bit more involved.

from javis.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.