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

Included in:
Cooltrainer::DistorteD::Technology::Vips
Defined in:
lib/distorted-floor/modular_technology/vips/load.rb

Constant Summary collapse

LOWER_WORLD =

Vips::vips_foreign_find_save is based on filename suffix (extension), but :vips_foreign_find_load seems to be based on file magic. That is, we can't `vips_foreign_find_load` for a made-up filename or plain suffix like we can to to build 'vips/save'::OUTER_LIMITS. This caught me off guard but doesn't entirely not-make-sense, considering Vips::Image::new_from_filename calls :vips_foreign_find_load and obviously expects a file to be present.

Example — works with real file and fails with only suffix: irb> Vips::vips_foreign_find_load '/home/okeeblow/cover.jpg'

> “VipsForeignLoadJpegFile”

irb> Vips::vips_foreign_find_load 'cover.jpg'

> nil

Syscalls of successful real-file :vips_foreign_find_load call showing how it works:

okeeblow@emi#okeeblow

strace ruby -e “require 'vips'; Vips::vips_foreign_find_load '/home/okeeblow/cover.jpg'” 2>&1|grep cover.jpg

access(“/home/okeeblow/cover.jpg”, R_OK) = 0 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY) = 5 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY) = 5 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY) = 5 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY) = 5 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY|O_CLOEXEC) = 5 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY|O_CLOEXEC) = 5 lstat(“/home/okeeblow/cover.jpg”, st_size=6242228, …) = 0 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY|O_CLOEXEC) = 5 stat(“/home/okeeblow/cover.jpg”, st_size=6242228, …) = 0 stat(“/home/okeeblow/cover.jpg-journal”, 0x7fffa70f4df0) = -1 ENOENT (No such file or directory) stat(“/home/okeeblow/cover.jpg-wal”, 0x7fffa70f4df0) = -1 ENOENT (No such file or directory) stat(“/home/okeeblow/cover.jpg”, st_size=6242228, …) = 0 openat(AT_FDCWD, “/home/okeeblow/cover.jpg”, O_RDONLY) = 5

…and of a fake suffix-only filename to show how it doesn't:

okeeblow@emi#okeeblow

strace ruby -e “require 'vips'; Vips::vips_foreign_find_load 'fartbutt.jpg'” 2>&1|grep '.jpg'

read(5, “.write_to_target target, ".jpg[Q”…, 8192) = 8192 access(“fartbutt.jpg”, R_OK) = -1 ENOENT (No such file or directory)

Versus the corresponding Vips::vips_foreign_find_save which is only based on filename suffix and does not try to look at a file at all, perhaps (read: obviously) because that file wouldn't exist yet to test until we save it :)

okeeblow@emi#okeeblow

strace ruby -e “require 'vips'; p Vips::vips_foreign_find_save 'fartbutt.jpg'” 2>&1|grep -E 'Save|.jpg'

read(5, “.write_to_target target, ".jpg[Q”…, 8192) = 8192 write(1, “"VipsForeignSaveJpegFile"n”, 26“VipsForeignSaveJpegFile”

For this reason I'm going to write my own shim Loader-finder and use it instead.

Cooltrainer::DistorteD::Technology::Vips::VipsType::loader_types.keep_if { |type, operations|
  # Skip text types for image data until I have a way for multiple
  # type-supporting Molecules to vote on a src file.
  # TODO: Support loading image CSV
  # TODO: Make this more robust/automatic.
  Array[
    type.phylum != :application,  # e.g. application/pdf
    type.phylum != :text,  # e.g. text/csv
  ].all? && Array[
    type.genus.to_s.include?(-'zip'),
    # Skip declaring SVG here since I want to handle it in a Vector-only Molecule
    # and will re-declare this there. Prolly need to think up a better way to do this.
    type.genus.to_s.include?(-'svg'),
  ].none?
}.transform_values { |v| v.map(&:options).reduce(&:merge) }

Instance Method Summary collapse

Instance Method Details

#to_vips_image(change = nil) ⇒ Object

Returns a Vips::Image from a file source. TODO: Get rid of this method! This is an old entrypoint.

Consume lower Types as a Change once we support Change chaining, then execute a chain.


159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/distorted-floor/modular_technology/vips/load.rb', line 159

def to_vips_image(change = nil)
  @vips_image ||= begin
    lower_config = the_setting_sun(:lower_world, *(type_mars.first&.settings_paths)) || Hash.new
    atoms = Hash.new
    lower_world[type_mars.first].values.reduce(&:concat).each_pair { |aka, compound|
      next if aka != compound.element  # Skip alias Compounds since they will all be handled at once.
      atoms.store(compound.element, Cooltrainer::Atom.new(compound.isotopes.reduce(nil) { |value, isotope|
        value || lower_config.fetch(isotope, nil) || context_arguments&.fetch(isotope, nil)
      }, compound.default))
    }
    self.send(type_mars.first.distorted_open_method, **atoms.transform_values(&:get))
  end
end