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

Method listing supported "foreign" extensions #269

aleksandrs-ledovskis started this conversation in Ideas
Discussion options

This is a feature request.

Would it be possible to add class method to Vips that would return an array of supported file formats akin to $ vips -l foreign does? Having such introspection would allow to programmatically decide if for example Vips supports any given format for transformation operation.

If there already exists a way how to get list of Vips' supported extensions, I'm all ears.

You must be logged in to vote

Replies: 7 comments

Comment options

Hello @aleksandrs-ledovskis,

You can do this now, though it's a little painful. Have a look at:

https://github.com/libvips/ruby-vips/blob/master/lib/vips/image.rb#L1341

The generate_yard method that makes the ruby-vips docs.

You would use GObject::g_type_from_name("VipsForeign") to get the GType for the base class of the file load/save operations (it's just an int), then walk all the subclasses recursively with Vips::vips_type_map looking for non-abstract types. You can instantiate an object of that type and get the text description, a list of the arguments, and the properties of each argument.

You can get things like supported suffixes too, though you'd need to add a little more ffi for that.

You must be logged in to vote
0 replies
Comment options

Spent some time digging in ruby-vips/libvips and managed to get some PoC code

require "vips"
require "set"
module Vips
 attach_function :vips_class_find, [:string, :string], :pointer
 attach_function :vips_object_summary_class, [:pointer, :pointer], :void
 class BufStruct < FFI::Struct
 layout :base, :pointer,
 :mx, :int,
 :i, :int,
 :full, :bool,
 :lasti, :int,
 :dynamic, :bool
 end
end
nicknames = []
generate_class = lambda do |gtype, _|
 nickname = Vips.nickname_find(gtype)
 nicknames << nickname if nickname
 Vips.vips_type_map(gtype, generate_class, nil)
end
generate_class.call(
 GObject.g_type_from_name("VipsForeign"),
 nil
)
extensions = Set.new
nicknames.each do |nickname|
 foreign_class = Vips.vips_class_find("VipsForeignLoad", nickname)
 next if foreign_class.null?
 buf_struct = Vips::BufStruct.new
 buf_struct_string = FFI::MemoryPointer.new(:char, 2048)
 buf_struct[:base] = buf_struct_string
 buf_struct[:mx] = 2048
 Vips.vips_object_summary_class(foreign_class, buf_struct.pointer)
 class_summary = buf_struct_string.read_string
 extensions.merge(class_summary.scan(/\.\w+\.?\w+/))
end
puts extensions

On my machine/libvips configuration outputs:

#<Set: {".csv", ".mat", ".vips", ".img", ".hdr", ".ppm", ".pgm", ".pbm", ".pfm", ".pdf", ".svg", ".svgz", ".svg.gz", ".gif", ".png", ".jpg", ".jpeg", ".jpe", ".webp", ".tif", ".tiff"}>

I couldn't make access to foreign_class->suffs work via FFI. There isn't existing ForeignClass mapping in ruby-vips and making a simplistic pointer-to-struct didn't work.

 class ForeignClassStruct < FFI::Struct
 layout :parent, GObject::GObject::Struct,
 :constructed, :int,
 :static_object, :int,
 :argument_table, :pointer,
 :nickname, :string,
 :description, :string,
 :preclose, :int,
 :close, :int,
 :postclose, :int,
 :local_memory, :size_t,
 :priority, :int,
 :chars, :pointer
 end
 # Junk
 ForeignClassStruct.new(Vips.vips_class_find("VipsForeignLoad", "pngload"))[:nickname]
 ForeignClassStruct.new(Vips.vips_class_find("VipsForeignLoad", "pngload"))[:priority]
You must be logged in to vote
0 replies
Comment options

@aleksandrs-ledovskis I am using this method here through command-line:

https://github.com/tomasc/dragonfly_libvips/blob/master/lib/dragonfly_libvips.rb#L19

But indeed, would be great to have a method of ruby-vips that outputs such list.

You must be logged in to vote
0 replies
Comment options

I had a quick hack and added get_suffixes:

$ irb
irb(main):001:0> require 'vips'
=> true
irb(main):002:0> Vips::get_suffixes
=> [".csv", ".mat", ".v", ".vips", ".ppm", ".pgm", ".pbm", ".pfm", ".hdr", ".dz", ".png", ".jpg", ".jpeg", ".jpe", ".webp", ".tif", ".tiff", ".fits", ".fit", ".fts", ".nii", ".nii.gz", ".hdr.gz", ".img", ".img.gz", ".nia", ".nia.gz", ".heic", ".gif", ".bmp"]
irb(main):003:0> 

Does that look reasonable? I'll add some tests as well.

You must be logged in to vote
0 replies
Comment options

Fabulous!

You must be logged in to vote
0 replies
Comment options

@jcupitt I see that you are basing the output on VipsForeignSave. If I compare "save" vs. "load" class extensions, there are some differences (e.g. SVG/PDFs are only supported as input and BMP as output).

As I use Vips for image processing I would be (more) interested in seeing a way to determine what extensions can be processed by Vips at the intake for purpose of populating texts visible to end-user ("Please upload image in ".jpg", ".jpeg" or ".png" formats)/doing pre-emptive validations based on file name.

@tomasc's case also seems to require both "load" and "save" extensions.

You must be logged in to vote
0 replies
Comment options

Hi @aleksandrs-ledovskis, yes, that's true. libvips uses the suffix to pick savers, so there's a simple relationship between filetype and extension. But loaders are picked by sniffing the first few bytes of the file, so a list of extensions won't always be complete.

I tried swapping it for VipsForeignLoad and I see:

irb(main):004:0> Vips::get_suffixes
=> [".v", ".vips", ".ppm", ".pgm", ".pbm", ".pfm", ".png", ".exr", ".svs", ".vms", 
".vmu", ".ndpi", ".scn", ".mrxs", ".svslide", ".tif", ".bif", ".jpg", ".jpeg", ".jpe", 
".tiff", ".csv", ".pdf", ".svg", ".svgz", ".svg.gz", ".gif", ".mat", ".webp", ".img", 
".hdr", ".fits", ".fit", ".fts", ".nii", ".nii.gz", ".hdr.gz", ".img.gz", ".nia", ".nia.gz"]

I don't know how useful that is. It's missing .ico and .bmp; .jpg is there three times, etc.

If you want a list of the available loaders, just walking the types below VipsForeignLoad might be simpler.

(libvips will load BMP, btw)

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
Ideas
Labels
None yet
Converted from issue

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

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