Module: Vips
- Extended by:
- FFI::Library
- Defined in:
- lib/vips.rb,
lib/vips/size.rb,
lib/vips/align.rb,
lib/vips/angle.rb,
lib/vips/image.rb,
lib/vips/access.rb,
lib/vips/coding.rb,
lib/vips/extend.rb,
lib/vips/kernel.rb,
lib/vips/object.rb,
lib/vips/angle45.rb,
lib/vips/methods.rb,
lib/vips/version.rb,
lib/vips/direction.rb,
lib/vips/operation.rb,
lib/vips/bandformat.rb,
lib/vips/interesting.rb,
lib/vips/interpolate.rb,
lib/vips/operationmath.rb,
lib/vips/interpretation.rb,
lib/vips/operationmath2.rb,
lib/vips/operationround.rb,
lib/vips/operationboolean.rb,
lib/vips/operationcomplex.rb,
lib/vips/compass_direction.rb,
lib/vips/operationcomplex2.rb,
lib/vips/operationcomplexget.rb,
lib/vips/operationrelational.rb
Overview
This module provides a binding for the libvips image processing library.
Example
require 'vips'
if ARGV.length < 2
raise "usage: #{$PROGRAM_NAME}: input-file output-file"
end
im = Vips::Image.new_from_file ARGV[0], access: :sequential
im *= [1, 2, 1]
mask = Vips::Image.new_from_array [
[-1, -1, -1],
[-1, 16, -1],
[-1, -1, -1]
], 8
im = im.conv mask, precision: :integer
im.write_to_file ARGV[1]
This example loads a file, boosts the green channel (I'm not sure why), sharpens the image, and saves it back to disc again.
Reading this example line by line, we have:
im = Vips::Image.new_from_file ARGV[0], access: :sequential
Image.new_from_file can load any image file supported by vips. In this
example, we will be accessing pixels top-to-bottom as we sweep through the
image reading and writing, so :sequential
access mode is best for us. The
default mode is :random
: this allows for full random access to image pixels,
but is slower and needs more memory. See Access
for full details
on the various modes available.
You can also load formatted images from memory buffers, create images that wrap C-style memory arrays, or make images from constants.
The next line:
im *= [1, 2, 1]
Multiplying the image by an array constant uses one array element for each image band. This line assumes that the input image has three bands and will double the middle band. For RGB images, that's doubling green.
Next we have:
mask = Vips::Image.new_from_array [
[-1, -1, -1],
[-1, 16, -1],
[-1, -1, -1]
], 8
im = im.conv mask, precision: :integer
Image.new_from_array creates an image from an array constant. The 8 at the end sets the scale: the amount to divide the image by after integer convolution.
See the libvips API docs for vips_conv()
(the operation
invoked by Image#conv) for details on the convolution operator. By default,
it computes with a float mask, but :integer
is fine for this case, and is
much faster.
Finally:
im.write_to_file ARGV[1]
Image#write_to_file writes an image back to the filesystem. It can write any format supported by vips: the file type is set from the filename suffix. You can also write formatted images to memory buffers, or dump image data to a raw memory array.
How it works
The binding uses ruby-ffi to open the libvips shared library. When you call a method on the image class, it uses libvips introspection system (based on GObject) to search the library for an operation of that name, transforms the arguments to a form libvips can digest, and runs the operation.
This means ruby-vips always presents the API implemented by the libvips shared library. It should update itself as new features are added.
Automatic wrapping
ruby-vips
adds a Image.method_missing handler to Image and uses
it to look up vips operations. For example, the libvips operation add
, which
appears in C as vips_add()
, appears in Ruby as Image#add.
The operation's list of required arguments is searched and the first input
image is set to the value of self
. Operations which do not take an input
image, such as Image.black, appear as class methods. The remainder of
the arguments you supply in the function call are used to set the other
required input arguments. Any trailing keyword arguments are used to set
options on the operation.
The result is the required output argument if there is only one result, or an array of values if the operation produces several results. If the operation has optional output objects, they are returned as a final hash.
For example, Image#min, the vips operation that searches an image for the minimum value, has a large number of optional arguments. You can use it to find the minimum value like this:
min_value = image.min
You can ask it to return the position of the minimum with :x
and :y
.
min_value, opts = min x: true, y: true
x_pos = opts['x']
y_pos = opts['y']
Now x_pos
and y_pos
will have the coordinates of the minimum value.
There's actually a convenience method for this, Image#minpos.
You can also ask for the top n minimum, for example:
min_value, opts = min size: 10, x_array: true, y_array: true
x_pos = opts['x_array']
y_pos = opts['y_array']
Now x_pos
and y_pos
will be 10-element arrays.
Because operations are member functions and return the result image, you can chain them. For example, you can write:
result_image = image.real.cos
to calculate the cosine of the real part of a complex image. There are also a full set of arithmetic operator overloads, see below.
libvips types are also automatically wrapped. The override looks at the type
of argument required by the operation and converts the value you supply,
when it can. For example, Image#linear takes a VipsArrayDouble
as
an argument
for the set of constants to use for multiplication. You can supply this
value as an integer, a float, or some kind of compound object and it
will be converted for you. You can write:
result_image = image.linear 1, 3
result_image = image.linear 12.4, 13.9
result_image = image.linear [1, 2, 3], [4, 5, 6]
result_image = image.linear 1, [4, 5, 6]
And so on. A set of overloads are defined for Image#linear, see below.
It does a couple of more ambitious conversions. It will automatically convert
to and from the various vips types, like VipsBlob
and VipsArrayImage
. For
example, you can read the ICC profile out of an image like this:
profile = im.get_value "icc-profile-data"
and profile will be a byte array.
If an operation takes several input images, you can use a constant for all but one of them and the wrapper will expand the constant to an image for you. For example, Image#ifthenelse uses a condition image to pick pixels between a then and an else image:
result_image = condition_image.ifthenelse then_image, else_image
You can use a constant instead of either the then or the else parts and it will be expanded to an image for you. If you use a constant for both then and else, it will be expanded to match the condition image. For example:
result_image = condition_image.ifthenelse [0, 255, 0], [255, 0, 0]
Will make an image where true pixels are green and false pixels are red.
This is useful for Image#bandjoin, the thing to join two or more images up bandwise. You can write:
rgba = rgb.bandjoin 255
to append a constant 255 band to an image, perhaps to add an alpha channel. Of course you can also write:
result_image = image1.bandjoin image2
result_image = image1.bandjoin [image2, image3]
result_image = Vips::Image.bandjoin [image1, image2, image3]
result_image = image1.bandjoin [image2, 255]
and so on.
Logging
Libvips uses g_log() to log warning, debug, info and (some) error messages.
https://developer.gnome.org/glib/stable/glib-Message-Logging.html
You can disable wanrings by defining the VIPS_WARNING
environment variable.
You can enable info output by defining VIPS_INFO
.
Exceptions
The wrapper spots errors from vips operations and raises the Error exception. You can catch it in the usual way.
Automatic YARD documentation
The bulk of these API docs are generated automatically by generate_yard. It examines libvips and writes a summary of each operation and the arguments and options that that operation expects.
Use the C API docs for more detail.
Enums
The libvips enums, such as VipsBandFormat
appear in ruby-vips as Symbols
like :uchar
. They are documented as a set of classes for convenience, see
the class list.
Draw operations
Paint operations like Image#draw_circle and Image#draw_line modify their input image. This makes them hard to use with the rest of libvips: you need to be very careful about the order in which operations execute or you can get nasty crashes.
The wrapper spots operations of this type and makes a private copy of the image in memory before calling the operation. This stops crashes, but it does make it inefficient. If you draw 100 lines on an image, for example, you'll copy the image 100 times. The wrapper does make sure that memory is recycled where possible, so you won't have 100 copies in memory.
If you want to avoid the copies, you'll need to call drawing operations yourself.
Overloads
The wrapper defines the usual set of arithmetic, boolean and relational overloads on image. You can mix images, constants and lists of constants (almost) freely. For example, you can write:
result_image = ((image * [1, 2, 3]).abs < 128) | 4
Expansions
Some vips operators take an enum to select an action, for example Image#math can be used to calculate sine of every pixel like this:
result_image = image.math :sin
This is annoying, so the wrapper expands all these enums into separate members named after the enum. So you can write:
result_image = image.sin
Convenience functions
The wrapper defines a few extra useful utility functions: Image#get_value, Image#set_value, Image#bandsplit, Image#maxpos, Image#minpos, Image#median.
Defined Under Namespace
Classes: Access, Align, Angle, Angle45, Argument, ArgumentClass, ArgumentClassPtr, ArgumentInstance, ArgumentInstancePtr, BandFormat, Coding, CompassDirection, Direction, Error, Extend, Image, IntStruct, Interesting, Interpolate, Interpretation, Kernel, Object, ObjectClass, Operation, OperationBoolean, OperationComplex, OperationComplex2, OperationComplexget, OperationMath, OperationMath2, OperationRelational, OperationRound, Size, SizeStruct
Constant Summary collapse
- LOG_DOMAIN =
"VIPS"
- LIBRARY_VERSION =
Vips::version_string
- MAX_COORD =
libvips has this arbitrary number as a sanity-check upper bound on image size. It's sometimes useful for know whan calculating image ratios.
10000000
- IMAGE_TYPE =
some handy gtypes
GObject::g_type_from_name "VipsImage"
- ARRAY_INT_TYPE =
GObject::g_type_from_name "VipsArrayInt"
- ARRAY_DOUBLE_TYPE =
GObject::g_type_from_name "VipsArrayDouble"
- ARRAY_IMAGE_TYPE =
GObject::g_type_from_name "VipsArrayImage"
- REFSTR_TYPE =
GObject::g_type_from_name "VipsRefString"
- BLOB_TYPE =
GObject::g_type_from_name "VipsBlob"
- BAND_FORMAT_TYPE =
Vips::vips_band_format_get_type
- INTERPRETATION_TYPE =
Vips::vips_interpretation_get_type
- CODING_TYPE =
Vips::vips_coding_get_type
- BLEND_MODE_TYPE =
nil
- VERSION =
"2.0.13"
Class Method Summary collapse
-
.at_least_libvips?(x, y) ⇒ Boolean
True if this is at least libvips x.y.
-
.cache_set_max(size) ⇒ Object
Set the maximum number of operations that libvips should cache.
-
.cache_set_max_files(size) ⇒ Object
Set the maximum number of files libvips should keep open in the operation cache.
-
.cache_set_max_mem(size) ⇒ Object
Set the maximum amount of memory that libvips should use for the operation cache.
-
.concurrency_set(n) ⇒ Object
Set the size of the libvips worker pool.
-
.generate_yard ⇒ Object
This method generates yard comments for all the dynamically bound vips operations.
-
.leak_set(leak) ⇒ Object
Turn libvips leak testing on and off.
-
.set_debug(debug) ⇒ Object
Deprecated compatibility function.
-
.vector_set(enabled) ⇒ Object
Enable or disable SIMD and the run-time compiler.
Class Method Details
.at_least_libvips?(x, y) ⇒ Boolean
True if this is at least libvips x.y
576 577 578 579 580 581 |
# File 'lib/vips.rb', line 576 def self.at_least_libvips?(x, y) major = version(0) minor = version(1) major > x || (major == x && minor >= y) end |
.cache_set_max(size) ⇒ Object
Set the maximum number of operations that libvips should cache. Set 0 to disable the operation cache. The default is 1000.
533 534 535 |
# File 'lib/vips.rb', line 533 def self.cache_set_max size vips_cache_set_max size end |
.cache_set_max_files(size) ⇒ Object
Set the maximum number of files libvips should keep open in the operation cache. Set 0 to disable the operation cache. The default is 100.
546 547 548 |
# File 'lib/vips.rb', line 546 def self.cache_set_max_files size vips_cache_set_max_files size end |
.cache_set_max_mem(size) ⇒ Object
Set the maximum amount of memory that libvips should use for the operation cache. Set 0 to disable the operation cache. The default is 100mb.
539 540 541 |
# File 'lib/vips.rb', line 539 def self.cache_set_max_mem size vips_cache_set_max_mem size end |
.concurrency_set(n) ⇒ Object
Set the size of the libvips worker pool. This defaults to the number of hardware threads on your computer. Set to 1 to disable threading.
552 553 554 |
# File 'lib/vips.rb', line 552 def self.concurrency_set n vips_concurrency_set n end |
.generate_yard ⇒ Object
This method generates yard comments for all the dynamically bound vips operations.
Regenerate with something like:
$ ruby > methods.rb
require 'vips'; Vips::generate_yard
^D
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 |
# File 'lib/vips/image.rb', line 1351 def self.generate_yard # these have hand-written methods, see above no_generate = ["scale", "bandjoin", "composite", "ifthenelse"] # map gobject's type names to Ruby map_go_to_ruby = { "gboolean" => "Boolean", "gint" => "Integer", "gdouble" => "Float", "gfloat" => "Float", "gchararray" => "String", "VipsImage" => "Vips::Image", "VipsInterpolate" => "Vips::Interpolate", "VipsArrayDouble" => "Array<Double>", "VipsArrayInt" => "Array<Integer>", "VipsArrayImage" => "Array<Image>", "VipsArrayString" => "Array<String>", } generate_operation = lambda do |gtype, nickname, op| op_flags = op.get_flags return if (op_flags & OPERATION_DEPRECATED) != 0 return if no_generate.include? nickname description = Vips::vips_object_get_description op # find and classify all the arguments the operator can take required_input = [] optional_input = [] required_output = [] optional_output = [] member_x = nil op.argument_map do |pspec, argument_class, argument_instance| arg_flags = argument_class[:flags] next if (arg_flags & ARGUMENT_CONSTRUCT) == 0 next if (arg_flags & ARGUMENT_DEPRECATED) != 0 name = pspec[:name].tr("-", "_") # 'in' as a param name confuses yard name = "im" if name == "in" gtype = pspec[:value_type] fundamental = GObject::g_type_fundamental gtype type_name = GObject::g_type_name gtype if map_go_to_ruby.include? type_name type_name = map_go_to_ruby[type_name] end if fundamental == GObject::GFLAGS_TYPE || fundamental == GObject::GENUM_TYPE type_name = "Vips::" + type_name[/Vips(.*)/, 1] end blurb = GObject::g_param_spec_get_blurb pspec value = {:name => name, :flags => arg_flags, :gtype => gtype, :type_name => type_name, :blurb => blurb} if (arg_flags & ARGUMENT_INPUT) != 0 if (arg_flags & ARGUMENT_REQUIRED) != 0 # note the first required input image, if any ... we # will be a method of this instance if !member_x && gtype == Vips::IMAGE_TYPE member_x = value else required_input << value end else optional_input << value end end # MODIFY INPUT args count as OUTPUT as well if (arg_flags & ARGUMENT_OUTPUT) != 0 || ((arg_flags & ARGUMENT_INPUT) != 0 && (arg_flags & ARGUMENT_MODIFY) != 0) if (arg_flags & ARGUMENT_REQUIRED) != 0 required_output << value else optional_output << value end end end print "# @!method " print "self." unless member_x print "#{nickname}(" print required_input.map{|x| x[:name]}.join(", ") print ", " if required_input.length > 0 puts "opts = {})" puts "# #{description.capitalize}." required_input.each do |arg| puts "# @param #{arg[:name]} [#{arg[:type_name]}] " + "#{arg[:blurb]}" end puts "# @param opts [Hash] Set of options" optional_input.each do |arg| puts "# @option opts [#{arg[:type_name]}] :#{arg[:name]} " + "#{arg[:blurb]}" end optional_output.each do |arg| print "# @option opts [#{arg[:type_name]}] :#{arg[:name]}" puts " Output #{arg[:blurb]}" end print "# @return [" if required_output.length == 0 print "nil" elsif required_output.length == 1 print required_output.first[:type_name] elsif print "Array<" print required_output.map{|x| x[:type_name]}.join(", ") print ">" end if optional_output.length > 0 print ", Hash<Symbol => Object>" end print "] " print required_output.map{|x| x[:blurb]}.join(", ") if optional_output.length > 0 print ", " if required_output.length > 0 print "Hash of optional output items" end puts "" puts "" end generate_class = lambda do |gtype, a| nickname = Vips::nickname_find gtype if nickname begin # can fail for abstract types op = Vips::Operation.new nickname rescue end generate_operation.(gtype, nickname, op) if op end Vips::vips_type_map gtype, generate_class, nil end puts "module Vips" puts " class Image" puts "" generate_class.(GObject::g_type_from_name("VipsOperation"), nil) puts " end" puts "end" end |
.leak_set(leak) ⇒ Object
Turn libvips leak testing on and off. Handy for debugging ruby-vips, not very useful for user code.
523 524 525 |
# File 'lib/vips.rb', line 523 def self.leak_set leak vips_leak_set (leak ? 1 : 0) end |
.set_debug(debug) ⇒ Object
Deprecated compatibility function.
Don't use this, instead change GLib::logger.level.
566 567 568 569 570 |
# File 'lib/vips.rb', line 566 def self.set_debug debug if debug GLib::logger.level = Logger::DEBUG end end |
.vector_set(enabled) ⇒ Object
Enable or disable SIMD and the run-time compiler. This can give a nice speed-up, but can also be unstable on some systems or with some versions of the run-time compiler.
559 560 561 |
# File 'lib/vips.rb', line 559 def self.vector_set enabled vips_vector_set_enabled(enabled ? 1 : 0) end |