All formats

ruby-vips (TIFF)

LanguageRuby
LicenseMIT (libvips: LGPL 2.1+)
Repositorygithub.com/libvips/ruby-vips
Documentationrubydoc.info/gems/ruby-vips, libvips tiffsave options
Depends onlibvips (system library, uses libtiff)
Read / writeyes / yes, multi-page, tiles, pyramids, BigTIFF, 8-32 bit and float, LZW, Deflate, PackBits, JPEG, ZSTD, WebP, CCITT Group 4

ruby-vips calls libvips through FFI. libvips processes images in a streaming pipeline, so it works on very large TIFFs with little memory and is many times faster than ImageMagick for resize and convert. It writes tiled and pyramidal TIFF, the layout used by slide scanners, GIS and deep zoom viewers. It’s the engine behind Rails Active Storage’s :vips processor.

Installation#

Shell
# install libvips first
sudo apt install libvips42    # Debian / Ubuntu
brew install vips             # macOS
gem install ruby-vips

Basic usage: open a TIFF and save as JPEG#

Ruby
require "vips"

image = Vips::Image.new_from_file("in.tif")  # first page
puts "#{image.width} x #{image.height}, #{image.bands} bands, #{image.format}"
puts "pages: #{image.get("n-pages")}" if image.get_typeof("n-pages") != 0
image.thumbnail_image(1200).write_to_file("out.jpg", Q: 85)

How to save a TIFF with compression#

Ruby
image = Vips::Image.new_from_file("in.png")
image.tiffsave("out.tif", compression: :lzw, predictor: :horizontal)
image.tiffsave("out_jpeg.tif", compression: :jpeg, Q: 90)
image.tiffsave("out_zstd.tif", compression: :zstd)

The same with a file name option string: image.write_to_file("out.tif[compression=deflate]").

How to read a specific page or all pages#

Ruby
page3 = Vips::Image.new_from_file("scan.tif", page: 2)  # 0-based

# all pages, stacked vertically in one tall image
all = Vips::Image.new_from_file("scan.tif", n: -1)
page_height = all.get("page-height")
pages = (0...(all.height / page_height)).map { |i| all.crop(0, i * page_height, all.width, page_height) }

How to write a multi-page TIFF#

Join the pages vertically, set page-height, and save:

Ruby
pages = %w[page1.png page2.png page3.png].map { |f| Vips::Image.new_from_file(f) }
doc = Vips::Image.arrayjoin(pages, across: 1)
doc = doc.mutate { |m| m.set_type!(GObject::GINT_TYPE, "page-height", pages.first.height) }
doc.tiffsave("pages.tif", compression: :lzw)

All pages must have the same width and height.

How to write a tiled, pyramidal BigTIFF#

Ruby
image = Vips::Image.new_from_file("huge.png", access: :sequential)
image.tiffsave("pyramid.tif", tile: true, tile_width: 256, tile_height: 256,
               pyramid: true, compression: :jpeg, Q: 85, bigtiff: true)

Tips#