Module: Cooltrainer::DistorteD::Technology::Vips

Includes:
Load, Save
Included in:
Molecule::Image
Defined in:
lib/distorted/modular_technology/vips.rb,
lib/distorted/modular_technology/vips/foreign.rb

Defined Under Namespace

Modules: Load, Save

Constant Summary collapse

TOP_LEVEL_LOADER =

All of the actual Loader/Saver classes we need to interact with will be tree children of one of these top-level class categories:

:VipsForeignLoad
TOP_LEVEL_SAVER =
:VipsForeignSave
G_TYPE_VALUES =

This has got to be built in to Ruby-GLib somewhere, right? Remove this if an FFI method is possible to get this mapping.

{
  :gboolean => [false, true],
  :gchararray => String,
  :gdouble => Float,
  :gint => Integer,
}
VIPS_ALIASES =

Aliases we want to support for consistency and accessibility.

{
  :Q => Set[:Q, :quality],
  :colours => Set[:colours, :colors],
  :centre => Set[:centre, :center],  # America; FUCK YEAH!
}
VIPS_VALID =

GEnum valid values are detectable, but I don’t know how to do the same for the numeric parameters. Specify them here manually for now.

{
  :"page-height" => (0..Vips::MAX_COORD),
  :"quant-table" => (0..8),
  :Q => (0..100),
  :colours => (2..256),
  :dither => (0.0..1.0),
  :compression => (0..9),
  :"alpha-q" => (0..100),
  :"reduction-effort" => (0..6),
  :kmin => (0..0x7FFFFFFF),  # https://en.wikipedia.org/wiki/2,147,483,647
  :kmax => (0..0x7FFFFFFF),
  :"tile-width" => (0..0x8000),  # 32768
  :"tile-height" => (0..0x8000),
  :xres => (0.001..1e+06),
  :yres => (0.001..1e+06),
}
VIPS_DEFAULT =

Same with default values for numeric parameters.

{
  :Q => 75,
  :colours => 256,
  :compression => 6,
  :"alpha-q" => 100,
  :"reduction-effort" => 4,
  :kmin => 0x7FFFFFFF - 1,
  :kmax => 0x7FFFFFFF,
  :"tile-width" => 128,
  :"tile-height" => 128,
  :xres => 1,
  :yres => 1,
}
@@vips_foreign_types =

Store FFI results where possible to minimize memory churn ‘n’ general fragility.

@@vips_foreign_suffixes =
@@vips_foreign_options =

Constants included from Load

Load::LOWER_WORLD, Load::VIPS_LOADERS

Constants included from Save

Save::OUTER_LIMITS, Save::VIPS_SAVERS

Class Method Summary collapse

Methods included from Load

#to_vips_image

Class Method Details

.vips_foreign_find_load_suffix(filename) ⇒ Object

Returns a String libvips Loader class name most appropriate for the given filename suffix. This is a workaround for the fact that the built-in Vips::vips_foreign_find_load requires access of a real image file, and we are here talking only of hypothetical ones. See this method’s call site in ‘vips/load’ for more detailed comments on this.

irb(main):234:0> Vips::vips_filename_get_filename(‘fart.jpg’)

> #<FFI::Pointer address=0x0000561efe3d08e0>

irb(main):235:0> Vips::p2str(Vips::vips_filename_get_filename(‘fart.jpg’))

> “fart.jpg”

irb(main):236:0> File.extname(Vips::p2str(Vips::vips_filename_get_filename(‘fart.jpg’)))

> “.jpg”

irb(main):237:0> Vips::vips_foreign_find_save(File.extname(Vips::p2str(Vips::vips_filename_get_filename(‘fart.jpg’))))

> “VipsForeignSaveJpegFile”

Here are the available Operations I have on my laptop with libvips 8.8:

okeeblow@emi#okeeblow

vips -l|grep VipsForeign|grep File

VipsForeignLoadPdfFile (pdfload), load PDF with libpoppler (.pdf), priority=0, is_a, get_flags, get_flags_filename, header, load
VipsForeignLoadSvgFile (svgload), load SVG with rsvg (.svg, .svgz, .svg.gz), priority=0, is_a, get_flags, get_flags_filename, header, load
VipsForeignLoadGifFile (gifload), load GIF with giflib (.gif), priority=0, is_a, get_flags, get_flags_filename, header, load
VipsForeignLoadJpegFile (jpegload), load jpeg from file (.jpg, .jpeg, .jpe), priority=50, is_a, get_flags, header, load
VipsForeignLoadWebpFile (webpload), load webp from file (.webp), priority=0, is_a, get_flags, get_flags_filename, header, load
VipsForeignLoadTiffFile (tiffload), load tiff from file (.tif, .tiff), priority=50, is_a, get_flags, get_flags_filename, header, load
VipsForeignLoadMagickFile (magickload), load file with ImageMagick, priority=-100, is_a, get_flags, get_flags_filename, header
VipsForeignSaveRadFile (radsave), save image to Radiance file (.hdr), priority=0, rgb
VipsForeignSaveDzFile (dzsave), save image to deepzoom file (.dz), priority=0, any
VipsForeignSavePngFile (pngsave), save image to png file (.png), priority=0, rgba
VipsForeignSaveJpegFile (jpegsave), save image to jpeg file (.jpg, .jpeg, .jpe), priority=0, rgb-cmyk
VipsForeignSaveWebpFile (webpsave), save image to webp file (.webp), priority=0, rgba-only
VipsForeignSaveTiffFile (tiffsave), save image to tiff file (.tif, .tiff), priority=0, any
VipsForeignSaveMagickFile (magicksave), save file with ImageMagick (.gif, .bmp), priority=-100, any

You can notice differences such as a ‘dzsave` and `radsave` but no `dzload` or `radload`. This is why we can’t assume that HAS_SAVER == HAS_LOADER across the board. Other differences are invisible here, like different formats supported silently by ‘magickload`, so that Operation is the catch-all fallback if we don’t have any better idea.

We can try taking a MIME::Type’s ‘sub_type`, capitalizing it, and trying to find a Loader Operation by that name. irb(main):254:0> MIME::Types::type_for(’.heif’).last.sub_type.capitalize

> “Heif”

irb(main):255:0> MIME::Types::type_for(‘.jpg’).last.sub_type.capitalize

> “Jpeg”

NOTE: I’m writing this on an old install that lacks HEIF support in its libvips 8.8 installation, so this failure to find ‘VipsForeignLoadHeifFile’ is expected and correct for me! It probably won’t fail for you in the future, but I want to make sure to include some example of varying library capability and not assume capabilities based on libvips version:

irb(main):257:0> GObject::g_type_from_name(“VipsForeignLoad#MIME::Types::type_for(‘.jpg’).last.sub_type.capitalizeFile”)

> 94691057380176

irb(main):258:0> GObject::g_type_from_name(“VipsForeignLoad#MIME::Types::type_for(‘.heif’).last.sub_type.capitalizeFile”)

> 0



154
155
156
157
158
# File 'lib/distorted/modular_technology/vips/foreign.rb', line 154

def self.vips_foreign_find_load_suffix(filename)
  suffix = File.extname(Vips::p2str(Vips::vips_filename_get_filename('fart.jpg')))
  guessed_loader = "VipsForeignLoad#{CHECKING::YOU::OUT(suffix).first.sub_type.capitalize}File"
  return self::vips_foreign_valid_operation?(guessed_loader) ? guessed_loader : 'VipsForeignLoadMagickFile'.freeze
end

.vips_get_options(nickname) ⇒ Object

Returns a Hash of Compound attributes supported by a given libvips Loader/Saver class.



182
183
184
185
# File 'lib/distorted/modular_technology/vips/foreign.rb', line 182

def self.vips_get_options(nickname)
  return Hash if nickname.nil?
  @@vips_foreign_options[nickname.to_sym] ||= self::vips_get_nickname_options(nickname)
end

.vips_get_suffixes(basename) ⇒ Object

Returns a Set of String filename suffixes supported by a tree of libvips loader/saver classes.

The Array returned from self::vips_get_nickname_suffixes will be overloaded with all duplicate suffix possibilities for each Type according to libvips. e.g. This is unrelated to MIME::Type#preferred_extension!!



176
177
178
# File 'lib/distorted/modular_technology/vips/foreign.rb', line 176

def self.vips_get_suffixes(basename)
  @@vips_foreign_suffixes[basename.to_sym] ||= self::vips_get_suffixes_per_nickname(basename).values.each_with_object(Set[]) {|s,n| n.merge(s)}
end

.vips_get_types(basename) ⇒ Object

Returns a Set of MIME::Types based on the “supported suffix” lists generated by libvips and our other functions here in this Module.



163
164
165
166
167
# File 'lib/distorted/modular_technology/vips/foreign.rb', line 163

def self.vips_get_types(basename)
  @@vips_foreign_types[basename.to_sym] ||= self::vips_get_suffixes(basename).each_with_object(Set[]) { |suffix, types|
    types.merge(CHECKING::YOU::OUT(suffix))
  }
end