Skip to content

Let #call write to an already-open output in the #convert format #149

Description

@flavorjones

This is the output side of #147.

HotCell receives the destination as an open file descriptor, but it can't pass /dev/fd/N as destination:, because the savers pick the format from the path's extension. So HotCell saves to a scratch file named output.png and then copies that file into the descriptor (transforming.rb). That is an extra write and read of every output, plus tmpfs space for the scratch file.

ImageProcessing::Vips.source(src).convert("png").call(destination: "/dev/fd/5")
# Vips::Error: VipsForeignSave: "/dev/fd/5" is not a known file format

ImageProcessing::MiniMagick.source(src).loader(inherit_fds: [out]).convert("jpg").call(destination: "/dev/fd/5")
# writes a PNG

Proposal: when the destination has no extension, save in the #convert format.

  • vips: pick the saver with Vips.vips_foreign_find_save(".#{format}") and filter options as select_valid_saver_options does.
  • MiniMagick: write to "#{format}:#{destination}".

Destinations with an extension are unaffected. .saver(saver:) doesn't cover this, because it takes libvips operation names and skips option filtering.

Happy to open a PR, or to add a format: keyword to #call instead if you prefer.

I opened #150 with a concrete implementation, in case it helps.

Activity

  1. changed the title [-]Save to `/dev/fd/N` in the format passed to `#convert`[/-] [+]Let `#call` write to an already-open output in the `#convert` format[/+] on Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions