Skip to content

Formats not supported by VipsForeignSaveRawBuffer #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
anitagraham opened this issue Oct 22, 2021 · 6 comments
Closed

Formats not supported by VipsForeignSaveRawBuffer #319

anitagraham opened this issue Oct 22, 2021 · 6 comments
Labels

Comments

@anitagraham
Copy link

anitagraham commented Oct 22, 2021

I found - running the test suite for dragonfly-libvips - that there are several image formats which are not supported by ForeignSaveBuffer.

The formats are avif, bmp, dz, gif, hdr, heic, heif, jpc, jpt, jp2, j2c, j2k and webp.

dragonfly_libvips typically processes an image (resize, crop, encode), then returns it to the caller after writing the new image to a buffer so:

 img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(**output_options)),
        'name' => "temp.#{format}",
        'format' => format

I'm not familiar with all the image formats listed, but I can imagine wanting to handle webp or heic.
At the moment I have added them to a list of unsupported formats but I wonder if any, all or some should be added to foreign.

thanks

@jcupitt
Copy link
Member

jcupitt commented Oct 22, 2021

Hi @anitagraham,

They should mostly work. Perhaps you are missing some libraries?

For avif, heic, heif save to buffer you need heifsave_buffer, you can test for it like this:

$ vips heifsave_buffer
save image in HEIF format
usage:
   heifsave_buffer in [--option-name option-value ...]
where:
   in           - Image to save, input VipsImage
outputs:
   buffer       - Buffer to save to, output VipsBlob
optional arguments:
   Q            - Q factor, input gint
			default: 50
...

In 8.11, GIF save is done via magicksave_buffer. 8.12 has a new, dedicated GIF saver and should be out soon.

BMP is also via magicksave_buffer. Perhaps you have built libvips without imagemagick?

WEBP should work, perhaps you are missing the webp libraries?

JP2K should also work. Again, you need to configure with OpenJPEG.

I would check the summary table at the end of libvips configure. It sounds like a lot of things are not there.

@jcupitt
Copy link
Member

jcupitt commented Oct 22, 2021

I meant to say, libvips from 8.10 has a new low-level IO system based on source and target. These are generic read and write classes which can be connected to any source and destination.

The _buffer classes are tiny wrappers over source and target, so they ought to exist for every operation, with only a few exceptions.

The docs have some info on these classes in Ruby:

http://libvips.github.io/ruby-vips/Vips/Target.html

@jcupitt
Copy link
Member

jcupitt commented Oct 22, 2021

I made you a small test prog:

#!/usr/bin/ruby

require 'vips'

x = Vips::Image.new_from_file ARGV[0]

%w(dz hdr jpc jpt jp2 j2c j2k webp).each do |format|
  begin
    buf = x.write_to_buffer ".#{format}"
    puts "#{format}: written #{buf.length} bytes"
  rescue Vips::Error
    puts "#{format}: buffer write not supported"
  end
end

# imagemagick-based savers need to be told the for format to write twice :(
%w(bmp gif).each do |format|
  begin
    buf = x.write_to_buffer ".#{format}", format: format
    puts "#{format}: written #{buf.length} bytes"
  rescue Vips::Error
    puts "#{format}: buffer write not supported"
  end
end

# libheif buffer savers need to be told the format too
buf = x.write_to_buffer ".heif", compression: "hevc"
puts "heic: written #{buf.length} bytes"

buf = x.write_to_buffer ".heif", compression: "av1"
puts "avif: written #{buf.length} bytes"

I see:

$ ./anita.rb ~/pics/k2.jpg
dz: written 467759 bytes
hdr: written 9132971 bytes
jpc: written 274315 bytes
jpt: written 274315 bytes
jp2: written 274315 bytes
j2c: written 274315 bytes
j2k: written 274315 bytes
webp: written 122962 bytes
bmp: written 8913034 bytes
gif: written 1968473 bytes
heic: written 209233 bytes
avif: written 254465 bytes

The extra parameter for imagemagick is very unfortunate. That's with 8.11, 8.12 will fix the GIF one at least.

We ought to extend the target API a bit and fix all these stupid special cases.

@anitagraham
Copy link
Author

Yes - running the test script from my home folder gets the expected results. I'll have to see what's happening in the test environment. Thanks.

@anitagraham
Copy link
Author

Thanks John. Tests all passing now.

I appreciate the effort you put in - and have been putting in for a long time.
🥇

jcupitt added a commit to libvips/libvips that referenced this issue Oct 26, 2021
Currently, buffer and target savers are not told the format they should
write.

This is usually OK (the JPEG saver already knows it should write JPEG),
but some savers can write several formats, and these currently need an
extra parameter.

For example:

```ruby
buf = x.write_to_buffer ".bmp", format: "bmp"
```

The first ".bmp" gets libvips to pick magicksave, the second
`format:` param is necessary to tell magicksave to write BMP.

This patch makes `vips_image_write_to_buffer` and
`vips_image_write_to_target` add an extra image metadata item called
`format_string` which contains the string used to pick the write format.

Savers can use this extra field (if present) to pick a default save
format. In this case, the magick saver will extract the "bmp".

See: libvips/ruby-vips#319
@jcupitt
Copy link
Member

jcupitt commented Oct 29, 2021

8.12 will have a fixed-up buffer save system. With this code:

%w(bmp gif heif avif ppm pfm pgm pbm).each do |format|
  buf = x.write_to_buffer ".#{format}"
  puts "#{format}: written #{buf.length} bytes"
end

I now see:

$ ./anita.rb ~/pics/k2.jpg
bmp: written 8913034 bytes
gif: written 1653970 bytes
heif: written 209233 bytes
avif: written 254465 bytes
ppm: written 8908859 bytes
pfm: written 35635258 bytes
pgm: written 2969659 bytes
pbm: written 372791 bytes

Thanks for suggesting this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants