Skip to content
Dan Milne edited this page Sep 18, 2020 · 27 revisions

Examples

These examples are in https://github.com/jcupitt/ruby-vips/tree/master/example

Thumbnail an image

ruby-vips has a thumbnail operator that can make a high-quality image thumbnail efficiently. It has three forms: thumbnail from a file source; thumbnail from an image held as a string; and thumbnail from another image, that perhaps you've already processed.

#!/usr/bin/env ruby

# batch-process a lot of files
#
# this should run in constant memory -- if it doesn't, something has broken

require 'vips'

# benchmark thumbnail via a memory buffer
def via_memory(filename, thumbnail_width) 
    data = IO.binread(filename)

    thumb = Vips::Image.thumbnail_buffer data, thumbnail_width, crop: 'centre'

    thumb.write_to_buffer '.jpg'
end

# benchmark thumbnail via files
def via_files(filename, thumbnail_width) 
    thumb = Vips::Image.thumbnail filename, thumbnail_width, crop: 'centre'

    thumb.write_to_buffer '.jpg'
end

ARGV.each do |filename|
    puts "processing #{filename} ..."
    thumb = via_memory(filename, 500)
    # thumb = via_files(filename, 500)
end

Annotate an image

This example renders some text on to an image.

The ruby-vips text operator makes a one band uchar image with 0 for background and 255 for text, rather like an alpha channel.

To render text on to an image, you make the text image, then expand it to match the size of the image you are rendering to, then use the text mask with ifthenelse to pick between pixels from the image and a constant. ruby-vips uses small arrays to represent pixel values, so [255, 0, 0] is red.

#!/usr/bin/env ruby

require 'vips'

im = Vips::Image.new_from_file ARGV[0], access: :sequential

left_text = Vips::Image.text "left corner", dpi: 300
left = left_text.embed 50, 50, im.width, 150 

right_text = Vips::Image.text "right corner", dpi: 300
right = right_text.embed im.width - right_text.width - 50, 50, im.width, 150

footer = (left | right).ifthenelse(0, [255, 0, 0], blend: true)

im = im.insert footer, 0, im.height, expand: true   

im.write_to_file ARGV[1]

Daltonize

Implementation of the daltonize algorithm for adjusting images to aid legibility for colour-blind people.

#!/usr/bin/ruby

# daltonize an image with ruby-vips
# based on
# http://scien.stanford.edu/pages/labsite/2005/psych221/projects/05/ofidaner/colorblindness_project.htm
# see
# http://libvips.blogspot.co.uk/2013/05/daltonize-in-ruby-vips-carrierwave-and.html
# for a discussion of this code

require 'vips'

#Vips.set_debug true

# matrices to convert D65 XYZ to and from bradford cone space
xyz_to_brad = [
    [0.8951,  0.2664, -0.1614],
    [-0.7502,  1.7135,  0.0367],
    [0.0389, -0.0685,  1.0296]
]
brad_to_xyz = [
    [0.987, -0.147, 0.16],
    [0.432, 0.5184, 0.0493],
    [-0.0085, 0.04, 0.968]
]

im = Vips::Image.new_from_file ARGV[0]

# remove any alpha channel before processing
alpha = nil
if im.bands == 4
    alpha = im[3]
    im = im.extract_band 0, :n => 3 
end

begin
    # import to XYZ with lcms
    # if there's no profile there, we'll fall back to the thing below
    xyz = im.icc_import :embedded => true, :pcs => :xyz 
rescue Vips::Error
    # nope .. use the built-in converter instead
    xyz = im.colourspace :xyz
end

brad = xyz.recomb xyz_to_brad 

# through the Deuteranope matrix
# we need rows to sum to 1 in Bradford space --- the matrix in the original
# Python code sums to 1.742
deut = brad.recomb [
    [1, 0, 0],
    [0.7, 0, 0.3],
    [0, 0, 1]
]

xyz = deut.recomb brad_to_xyz 

# .. and back to sRGB 
rgb = xyz.colourspace :srgb

# so this is the colour error 
err = im - rgb

# add the error back to other channels to make a compensated image
im = im + err.recomb([
    [0, 0, 0], 
    [0.7, 1, 0],
    [0.7, 0, 1]
])

# reattach any alpha we saved above
if alpha
    im = im.bandjoin(alpha)
end

im.write_to_file ARGV[1] 

Creating image of a specific colour

Create a new image with specific pixel values ( from Stackoverflow ):

value = [ 50, 100, 150 ] # RBG Values
pixel = (Vips::Image.black(1, 1) + value).cast(:uint)
image = pixel.embed 0, 0, 1200, 630, extend: :copy

Create a composite image

Create a composite image from two other images:

background  = Vips::Image.new_from_file 'background.jpg'
photo = Vips::Image.new_from_file('600.jpeg') )

out = back.composite photo, "over", x: 100, y: 100
out.jpegsave('out.jpg')