-
Notifications
You must be signed in to change notification settings - Fork 61
Examples
You never iterate yourself through pixels one by one, it'd be much too slow.
Instead, imagine images are huge arrays of numbers and you have a library which can efficiently apply operations to those large matrices. Imagine what calculation the thing you want to do might correspond to, and just type it.
For example, to set the red and blue channels to zero and just leave a green image you might multiply r and b by zero and g by 1. A handy vips operation for this is "lin", meaning "linear transform").
out = in.lin(a, b)
sets every pixel in out to be
out = in * a + b
It lets you give an array of numbers for a and b and will use one array element per image channel. So therefore:
#!/usr/bin/ruby
require 'rubygems'
require 'vips'
include VIPS
im = Image.new 'mypic.jpg'
im = im.lin [0, 1, 0], [0, 0, 0]
im.write 'output.jpg'
To make a constant image (where all pixels have the same constant value), make a 1x1 pixel zero image with Image::black, add some amount to it with .lin(), and expand it up to the size you need with .embed().
#!/usr/bin/ruby
require 'rubygems'
require 'vips'
include VIPS
im = Image.black 1, 1, 1
im = im.lin [0, 0, 1], [0, 0, 0]
im = im.embed :extend, 0, 0, 400, 400
im.write 'constant_blue.jpg'
You can speed this up a slightly. lin() makes a floating-point image (since the parameters can be floats), and jpeg-save is automatically casting this back down to 8 bits before writing. If you cast to 8 bits yourself before expanding the image you can avoid a lot of upcasting and downcasting.
im = Image.black 1, 1, 1
im = im.lin([0, 0, 1], [0, 0, 0]).clip2fmt(:UCHAR)
im = im.embed :extend, 0, 0, 400, 400
im.write 'constant_blue.jpg'
To change image gamma you might try something like:
im = im.pow(0.5).lin(255 / 255 ** 0.5, 0)
Though that'll be a bit slow (it'll call pow() three times for each pixel), it'd be much faster to make a lookup table (see Basic concepts), run the pow() on that, then map the image through the table:
lut = Image.identity(1)
lut = lut.pow(0.5).lin(255 / 255 ** 0.5, 0)
im = im.maplut(lut)
Finally:
#!/usr/bin/ruby
require 'rubygems'
require 'vips'
include VIPS
im = Image.new 'mypic.jpg'
lut = Image.identity 1
gamma = 0.8
lut = lut.pow(gamma).lin(255 / 255 ** gamma, 0).clip2fmt(:UCHAR)
im = im.maplut lut
im.write 'output.jpg'
Implementation of the daltonize algorithm for correcting images for colour-blind people.
#!/usr/bin/ruby
# daltonize.rb - example implementation of the daltonize algorithm using ruby-vips
#
# This example only implements Deuternope, but can easily be adapted to include Protanope and Tritanope
#
# Usage: ruby daltonize.rb <source.jpeg> <output.jpeg>
#
# requires: ruby-vips
#
# credits:
# Written by John Cupitt - the maintainer of ruby-vips library
# Yoav Aner - applied small fixes and tweaks
#
# Resources and other implementations:
# javascript - http://www.daltonize.org/search/label/Javascript
# python - http://moinmo.in/AccessibleMoin?action=AttachFile&do=view&target=daltonize.py
# Daltonize.org - http://www.daltonize.org/
#
# "Analysis of Color Blindness" by Onur Fidaner, Poliang Lin and Nevran Ozguven.
# http://scien.stanford.edu/class/psych221/projects/05/ofidaner/project_report.pdf
#
# "Digital Video Colourmaps for Checking the Legibility of Displays by Dichromats" by Françoise Viénot,
# Hans Brettel and John D. Mollon
# http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf
require 'rubygems'
require 'vips'
im = VIPS::Image.jpeg(ARGV[0], :sequential => true)
begin
# import to CIELAB with lcms
# if there's no profile there, we'll fall back to the thing below
cielab = im.icc_import_embedded(:relative)
rescue VIPS::Error
# nope .. use the built-in converter instead
cielab = im.srgb_to_xyz().xyz_to_lab()
end
# turn to XYZ, a linear light space
xyz = cielab.lab_to_xyz()
# convert rgb to lms
lms = xyz.recomb([[17.8824, 43.5161, 4.11935],
[3.45565, 27.1554, 3.86714],
[0.0299566, 0.184309, 1.46709]])
# through the Deuteranope matrix
deut = lms.recomb([[1, 0, 0],
[0.494207, 0, 1.24827],
[0, 0, 1]])
# back to xyz (this is the inverse of the lms matrix above)
xyz = deut.recomb([[0.0809444479, -0.130504409, 0.116721066],
[-0.0102485335, 0.0540193266, -0.113614708],
[-0.000365296938, -0.00412161469, 0.693511405]])
# .. and export to sRGB for saving
rgb = xyz.xyz_to_srgb()
rgb.write(ARGV[1])