Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gif & anim-gif support #271

Unanswered
tomasc asked this question in Q&A
Discussion options

It seems is possible to output .gif files in libvips ~> 8.7.0 via command-line, but not using ruby-vips. Is that correct? Do we need to update ruby-vips somehow? If so, I can try to start a PR if you could point me to the right direction ...

You must be logged in to vote

Replies: 10 comments

Comment options

Hello @tomasc, it should just work, ruby-vips is supposed to self-update. I see:

$ irb
irb(main):001:0> require 'vips'
=> true
irb(main):002:0> x = Vips::Image.new_from_file "3198.gif"
=> #<Image 298x193 uchar, 3 bands, srgb>
irb(main):003:0> x.write_to_file "y.gif"
=> nil

Perhaps your ruby is picking up a libvips that's been built without magicksave? Try:

irb(main):004:0> x = Vips::Image.new_from_file "k2.jpg"
=> #<Image 1450x2048 uchar, 3 bands, srgb>
irb(main):005:0> x.magicksave "y.gif"
=> nil
You must be logged in to vote
0 replies
Comment options

@jcupitt indeed .write_to_file works. But .write_to_buffer is angry on me :-).

x = Vips::Image.new_from_file "3198.gif"
x.write_to_buffer(".gif")
Traceback (most recent call last):
 7: from .../.rbenv/versions/2.6.1/bin/irb:23:in `<main>'
 6: from .../.rbenv/versions/2.6.1/bin/irb:23:in `load'
 5: from .../.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
 4: from (irb):11
 3: from .../.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.13/lib/vips/image.rb:468:in `write_to_buffer'
 2: from .../.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.13/lib/vips/operation.rb:330:in `call'
 1: from .../.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.13/lib/vips/operation.rb:74:in `build'
Vips::Error (magicksave_buffer: libMagick error: no decode delegate for this image format `' @ error/blob.c/ImagesToBlob/2401)
You must be logged in to vote
0 replies
Comment options

Try to hint the file type:

x.write_to_buffer ".gif", format: "gif"
You must be logged in to vote
0 replies
Comment options

Yes, I guess magicksave should probably guess the format for you, if you don't set it explicitly.

You must be logged in to vote
0 replies
Comment options

@kleisauke @jcupitt yes that works! But only when saving to gif.

x = Vips::Image.new_from_file "sample.gif"
x.write_to_buffer(".jpg", format: "jpg")
Vips::Error: unable to call VipsForeignSaveJpegBuffer: unknown option format
You must be logged in to vote
0 replies
Comment options

In other words, it feels funny to hint the format only on certain formats (gif) – should not this work across the board?

You must be logged in to vote
0 replies
Comment options

It does seem weird. It's to do with the way that savers work in libvips.

libvips has a saver operation for each file format, so there's jpegsave, tiffsave, etc. These are ordinary libvips operations and you can call them like any other, eg.:

im.jpegsave "somefilename", Q: 85

There are versions with _buffer appended to make memory objects instead, and of course they don't take a filename argument:

str = im.jpegsave_buffer Q: 85

When a saver class is initialized, it registers a list of suffixes it supports with libvips, eg. ".jpg", ".jpeg" etc., so when you write:

im.write_to_file "somefile.jpg"

libvips extracts the suffix from the filename, then walks the saver list, searching for the highest priority saver which has registered that suffix. It then invokes that operation on your filename, passing down any options.

For buffer output, it passes down the options, but does not pass down the filename (why would you need a filename for buffer output?).

This causes problems for magicksave, which is a saver that can write many different formats. If there's a filename, it can detect it from that, but magicksave to a buffer has no idea what's going on.

I suppose the fix would be for write_to_buffer to pass the suffix down to the saver via an extra optional argument. It would need a bit of reworking of the logic in image.c somewhere.

You must be logged in to vote
0 replies
Comment options

Thanks, John. I worked around that for the time being in dargonfly_libvips.

To me, it would be make sense if write_to_buffer would only accept format (rather than extension).

You must be logged in to vote
0 replies
Comment options

Heh, I see I'm not the one who was confused by that there is some magic format guessing based on the extension.
#133

You must be logged in to vote
0 replies
Comment options

For anyone looking for how to preserve a gif's animation when generating variants with vips and ActiveStorage:

post.image.variant(loader: { n: -1 }, resize_to_limit: [400, 400])

with loader: { n: -1 } being the important bit that corresponds to the arguments passed to vips_gifload.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
Converted from issue

This discussion was converted from issue #189 on January 31, 2021 13:10.

AltStyle によって変換されたページ (->オリジナル) /