# How can I combine Cairo frames into a GIF?

**URL:** <https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [July 17, 2023, 7:20pm UTC](https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704 "2023-07-17T19:20:41Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![djpell](https://avatars.discourse-cdn.com/v4/letter/d/34f0e0/32.png) [@djpell](https://discourse.julialang.org/u/djpell)\
**Post date:** [July 17, 2023, 7:20pm UTC](https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704/1 "2023-07-17T19:20:41Z")

</div>

I have used Cairo to create a series of drawings collected into an array. I would like to combine all of these images into a GIF.

FileIO allows me to convert one single frame into a PNG with ` FileIO.save("test.png", imgs[1])` where `imgs` is my array of Cairo images. However, when I attempt to run `FileIO.save("test.gif", imgs)` I get the following error:

```julia
┌ Warning: Mapping to the storage type failed; perhaps your data had out-of-range values?
│ Try `map(clamp01nan, img)` to clamp values to a valid range.
└ @ ImageMagick C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:179
Error encountered while save File{DataFormat{:GIF}, String}("test.gif").

Fatal error:
MethodError: no method matching mapIM(::Cairo.CairoSurfaceBase{UInt32})
Closest candidates are:
  mapIM(::Gray{T}) where T<:FixedPointNumbers.Normed at C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:302
  mapIM(::Gray{T}) where T at C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:301
  mapIM(::FixedPointNumbers.Normed) at C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:321
  ...
Stacktrace:
  [1] (::ImageMagick.var"#42#43"{typeof(identity)})(x::Cairo.CairoSurfaceBase{UInt32})
    @ ImageMagick C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:177
  [2] iterate
    @ .\generator.jl:47 [inlined]
  [3] _collect
    @ .\array.jl:744 [inlined]
  [4] collect_similar(cont::Vector{Cairo.CairoSurfaceBase{UInt32}}, itr::Base.Generator{Vector{Cairo.CairoSurfaceBase{UInt32}}, ImageMagick.var"#42#43"{typeof(identity)}})
    @ Base .\array.jl:653
  [5] map(f::Function, A::Vector{Cairo.CairoSurfaceBase{UInt32}})
    @ Base .\abstractarray.jl:2849
  [6] image2wand(img::Any, mapi::typeof(identity), quality::Nothing, permute_horizontal::Bool; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ ImageMagick C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:177
  [7] image2wand
    @ C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:175 [inlined]
  [8] #save_#39
    @ C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:162 [inlined]
  [9] save_ (repeats 2 times)
    @ C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:162 [inlined]
 [10] save(imagefile::File, args::Any; key_args::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ ImageMagick C:\Users\[user]\.julia\packages\ImageMagick\Fh2BX\src\ImageMagick.jl:126

Stacktrace:
  [1] handle_error(e::MethodError, q::Base.PkgId, bt::Vector{Union{Ptr{Nothing}, Base.InterpreterIP}})
    @ FileIO C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\error_handling.jl:61
  [2] handle_exceptions(exceptions::Vector{Tuple{Any, Union{Base.PkgId, Module}, Vector}}, action::String)
    @ FileIO C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\error_handling.jl:56
  [3] action(call::Symbol, libraries::Vector{Union{Base.PkgId, Module}}, file::FileIO.Formatted, args::Vector{Cairo.CairoSurfaceBase{UInt32}}; options::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ FileIO C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:228
  [4] action
    @ C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:197 [inlined]
  [5] action(call::Symbol, libraries::Vector{Union{Base.PkgId, Module}}, sym::Symbol, file::String, args::Vector{Cairo.CairoSurfaceBase{UInt32}}; options::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ FileIO C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:185
  [6] action
    @ C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:185 [inlined]
  [7] #save#20
    @ C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:129 [inlined]
  [8] save(file::String, args::Vector{Cairo.CairoSurfaceBase{UInt32}})
    @ FileIO C:\Users\[user]\.julia\packages\FileIO\BE7iZ\src\loadsave.jl:126
  [9] top-level scope
    @ In[35]:1
 [10] eval
    @ .\boot.jl:373 [inlined]
 [11] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base .\loading.jl:1196

```

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [July 17, 2023, 8:19pm UTC](https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704/2 "2023-07-17T20:19:49Z")

</div>

Hi there! As a workround you could save the PNG images in a directory and then run use FFMPEG.jl to create the animation…

Without some example code that can be run, it’s not easy for people to find out what’s going on here.

---

<div class="post-metadata">

**Author:** ![djpell](https://avatars.discourse-cdn.com/v4/letter/d/34f0e0/32.png) [@djpell](https://discourse.julialang.org/u/djpell)\
**Post date:** [July 17, 2023, 8:26pm UTC](https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704/3 "2023-07-17T20:26:16Z")

</div>

I’m thinking I’ll attempt that.

Here’s an example:

```julia
img0 = CairoRGBSurface(512, 512)
cr = CairoContext(img0)

set_source_rgb(cr, 1, 0, 0)
Cairo.arc(cr, 256, 256, 10, 0, 2*\pi)
Cairo.stroke(cr)

imgs = [img0]

for i in 1:5
    img = CairoRGBSurface(0, 0, 0)
    cr = CairoContext(img)

    set_source_rgb(cr, 1, 0, 0)
    Cairo.arc(cr, 256+20*i, 256, 10, 0, 2*\pi)
    Cairo.stroke(cr)

    push!(imgs, img)
end

FileIO.save("test.gif", imgs)

```

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [July 17, 2023, 9:15pm UTC](https://discourse.julialang.org/t/how-can-i-combine-cairo-frames-into-a-gif/101704/4 "2023-07-17T21:15:48Z")

</div>

Yes, I think there are some issues with the GIF-saving - I’d stick to PNGs and FFMPEG myself… 🙂
