Before ruby-vips 1.0, I can get the array of RGB average colors using:
im.stats[1][4].to_i, im.stats[2][4].to_i, im.stats[3][4].to_i
But after update to ruby-vips 1.0, stats
method does not return a ruby array any more. I noticed there is an im.avg()
method, but it returns a scalar value, not separate values for RGB channels.
How to calculate image average colors using the new API?
For historical reasons libvips used to have its own array type. It had a whole set of functions for manipulating these arrays, all slightly different from the functions for manipulating images.
libvips8 has fixed this by removing the array type and using one-band double images instead. So the result of stats
is now a small image you can just read pixels values from.
Use getpoint
to read pixels from images:
http://www.rubydoc.info/gems/ruby-vips/1.0.0/Vips/Image#getpoint-instance_method
For example:
$ irb
irb(main):001:0> require 'vips'
=> true
irb(main):002:0> im = Vips::Image.new_from_file "/home/john/pics/k2.jpg"
=> #<Vips::Image:0x1c83830 ptr=0x1fb7020>
irb(main):003:0> im.getpoint(10, 10)
=> [10.0, 0.0, 3.0]
irb(main):004:0> im.stats
=> #<Vips::Image:0x20d1950 ptr=0x1fb7e30>
The layout of the image you get from stats is in the C docs (ruby-vips
is a thin layer over the C API, so all those docs work):
So you want column 4, rows 1, 2, 3 for the RGB averages. getpoint
returns an array, so for a one-band image, use [0]
to get the first element.
irb(main):007:0> im.stats.getpoint(4, 1)[0]
=> 110.87133688038793
irb(main):008:0> im.stats.getpoint(4, 2)[0]
=> 101.0471090382543
irb(main):009:0> im.stats.getpoint(4, 3)[0]
=> 96.45809502963363
This does seem a bit clumsy. Perhaps Image
should have a to_a
method? It would only make sense for very small images, of course.