ruby-vips 2.0.15 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/workflows/test.yml +80 -0
- data/.standard.yml +17 -0
- data/.yardopts +0 -1
- data/CHANGELOG.md +39 -0
- data/Gemfile +3 -1
- data/README.md +42 -41
- data/Rakefile +13 -21
- data/TODO +14 -14
- data/VERSION +1 -1
- data/example/annotate.rb +6 -6
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +6 -6
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +4 -4
- data/example/example2.rb +6 -6
- data/example/example3.rb +5 -5
- data/example/example4.rb +2 -2
- data/example/example5.rb +4 -4
- data/example/inheritance_with_refcount.rb +35 -36
- data/example/progress.rb +30 -0
- data/example/thumb.rb +6 -6
- data/example/trim8.rb +1 -1
- data/example/watermark.rb +2 -2
- data/example/wobble.rb +1 -1
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +191 -79
- data/lib/vips/blend_mode.rb +29 -25
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/gobject.rb +27 -12
- data/lib/vips/gvalue.rb +62 -50
- data/lib/vips/image.rb +475 -256
- data/lib/vips/interpolate.rb +3 -2
- data/lib/vips/methods.rb +788 -121
- data/lib/vips/mutableimage.rb +173 -0
- data/lib/vips/object.rb +171 -54
- data/lib/vips/operation.rb +272 -117
- data/lib/vips/region.rb +73 -0
- data/lib/vips/source.rb +88 -0
- data/lib/vips/sourcecustom.rb +89 -0
- data/lib/vips/target.rb +86 -0
- data/lib/vips/targetcustom.rb +77 -0
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +26 -20
- metadata +39 -50
- data/.rubocop.yml +0 -22
- data/.rubocop_todo.yml +0 -515
- data/.travis.yml +0 -62
- data/install-vips.sh +0 -26
data/example/trim8.rb
CHANGED
data/example/watermark.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
5
|
im = Vips::Image.new_from_file ARGV[0], access: :sequential
|
6
6
|
|
7
7
|
# make the text mask
|
8
|
-
text = Vips::Image.text ARGV[2], width: 200, dpi: 200, font:
|
8
|
+
text = Vips::Image.text ARGV[2], width: 200, dpi: 200, font: "sans bold"
|
9
9
|
text = text.rotate(-45)
|
10
10
|
# make the text transparent
|
11
11
|
text = (text * 0.3).cast(:uchar)
|
data/example/wobble.rb
CHANGED
data/lib/ruby-vips.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "vips"
|
data/lib/vips.rb
CHANGED
@@ -4,28 +4,45 @@
|
|
4
4
|
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
5
|
# License:: MIT
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "ffi"
|
8
|
+
require "logger"
|
9
9
|
|
10
10
|
# This module uses FFI to make a simple layer over the glib and gobject
|
11
11
|
# libraries.
|
12
12
|
|
13
|
+
# Generate a library name for ffi.
|
14
|
+
#
|
15
|
+
# Platform notes:
|
16
|
+
# linux:
|
17
|
+
# Some distros allow "libvips.so", but only if the -dev headers have been
|
18
|
+
# installed. To work everywhere, you must include the ABI number.
|
19
|
+
# Confusingly, the file extension is not at the end. ffi adds the "lib"
|
20
|
+
# prefix.
|
21
|
+
# mac:
|
22
|
+
# As linux, but the extension is at the end and is added by ffi.
|
23
|
+
# windows:
|
24
|
+
# The ABI number must be included, but with a hyphen. ffi does not add a
|
25
|
+
# "lib" prefix or a ".dll" suffix.
|
26
|
+
def library_name(name, abi_number)
|
27
|
+
if FFI::Platform.windows?
|
28
|
+
"lib#{name}-#{abi_number}.dll"
|
29
|
+
elsif FFI::Platform.mac?
|
30
|
+
"#{name}.#{abi_number}"
|
31
|
+
else
|
32
|
+
"#{name}.so.#{abi_number}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
13
36
|
module GLib
|
14
37
|
class << self
|
15
38
|
attr_accessor :logger
|
16
39
|
end
|
17
|
-
@logger = Logger.new(
|
40
|
+
@logger = Logger.new($stdout)
|
18
41
|
@logger.level = Logger::WARN
|
19
42
|
|
20
43
|
extend FFI::Library
|
21
44
|
|
22
|
-
|
23
|
-
glib_libname = 'libglib-2.0-0.dll'
|
24
|
-
else
|
25
|
-
glib_libname = 'glib-2.0'
|
26
|
-
end
|
27
|
-
|
28
|
-
ffi_lib glib_libname
|
45
|
+
ffi_lib library_name("glib-2.0", 0)
|
29
46
|
|
30
47
|
attach_function :g_malloc, [:size_t], :pointer
|
31
48
|
|
@@ -35,20 +52,20 @@ module GLib
|
|
35
52
|
|
36
53
|
callback :g_log_func, [:string, :int, :string, :pointer], :void
|
37
54
|
attach_function :g_log_set_handler,
|
38
|
-
|
55
|
+
[:string, :int, :g_log_func, :pointer], :int
|
39
56
|
attach_function :g_log_remove_handler, [:string, :int], :void
|
40
57
|
|
41
58
|
# log flags
|
42
|
-
LOG_FLAG_RECURSION
|
43
|
-
LOG_FLAG_FATAL
|
59
|
+
LOG_FLAG_RECURSION = 1 << 0
|
60
|
+
LOG_FLAG_FATAL = 1 << 1
|
44
61
|
|
45
62
|
# GLib log levels
|
46
|
-
LOG_LEVEL_ERROR
|
47
|
-
LOG_LEVEL_CRITICAL
|
48
|
-
LOG_LEVEL_WARNING
|
49
|
-
LOG_LEVEL_MESSAGE
|
50
|
-
LOG_LEVEL_INFO
|
51
|
-
LOG_LEVEL_DEBUG
|
63
|
+
LOG_LEVEL_ERROR = 1 << 2 # always fatal
|
64
|
+
LOG_LEVEL_CRITICAL = 1 << 3
|
65
|
+
LOG_LEVEL_WARNING = 1 << 4
|
66
|
+
LOG_LEVEL_MESSAGE = 1 << 5
|
67
|
+
LOG_LEVEL_INFO = 1 << 6
|
68
|
+
LOG_LEVEL_DEBUG = 1 << 7
|
52
69
|
|
53
70
|
# map glib levels to Logger::Severity
|
54
71
|
GLIB_TO_SEVERITY = {
|
@@ -66,9 +83,9 @@ module GLib
|
|
66
83
|
@glib_log_handler_id = 0
|
67
84
|
|
68
85
|
# module-level, so it's not GCd away
|
69
|
-
LOG_HANDLER =
|
86
|
+
LOG_HANDLER = proc { |domain, level, message, _user_data|
|
70
87
|
@logger.log(GLIB_TO_SEVERITY[level], message, domain)
|
71
|
-
|
88
|
+
}
|
72
89
|
|
73
90
|
def self.remove_log_handler
|
74
91
|
if @glib_log_handler_id != 0 && @glib_log_domain
|
@@ -78,7 +95,7 @@ module GLib
|
|
78
95
|
end
|
79
96
|
|
80
97
|
def self.set_log_domain domain
|
81
|
-
GLib
|
98
|
+
GLib.remove_log_handler
|
82
99
|
|
83
100
|
@glib_log_domain = domain
|
84
101
|
|
@@ -108,7 +125,7 @@ module GLib
|
|
108
125
|
# on shutdown and we don't want LOG_HANDLER to be invoked
|
109
126
|
# after Ruby has gone
|
110
127
|
at_exit {
|
111
|
-
GLib
|
128
|
+
GLib.remove_log_handler
|
112
129
|
}
|
113
130
|
end
|
114
131
|
end
|
@@ -117,13 +134,7 @@ end
|
|
117
134
|
module GObject
|
118
135
|
extend FFI::Library
|
119
136
|
|
120
|
-
|
121
|
-
gobject_libname = 'libgobject-2.0-0.dll'
|
122
|
-
else
|
123
|
-
gobject_libname = 'gobject-2.0'
|
124
|
-
end
|
125
|
-
|
126
|
-
ffi_lib gobject_libname
|
137
|
+
ffi_lib library_name("gobject-2.0", 0)
|
127
138
|
|
128
139
|
# we can't just use ulong, windows has different int sizing rules
|
129
140
|
if FFI::Platform::ADDRESS_SIZE == 64
|
@@ -151,11 +162,11 @@ module GObject
|
|
151
162
|
GOBJECT_TYPE = g_type_from_name "GObject"
|
152
163
|
end
|
153
164
|
|
154
|
-
require
|
155
|
-
require
|
165
|
+
require "vips/gobject"
|
166
|
+
require "vips/gvalue"
|
156
167
|
|
157
168
|
# This module provides a binding for the [libvips image processing
|
158
|
-
# library](https://
|
169
|
+
# library](https://libvips.github.io/libvips/).
|
159
170
|
#
|
160
171
|
# # Example
|
161
172
|
#
|
@@ -197,9 +208,10 @@ require 'vips/gvalue'
|
|
197
208
|
# for full details
|
198
209
|
# on the various modes available.
|
199
210
|
#
|
200
|
-
# You can also load formatted images from
|
201
|
-
#
|
202
|
-
# from
|
211
|
+
# You can also load formatted images from memory buffers, create images that
|
212
|
+
# wrap C-style memory arrays, or make images from constants. Use {Source}
|
213
|
+
# and {Image.new_from_source} to load images from any data source, for
|
214
|
+
# example URIs.
|
203
215
|
#
|
204
216
|
# The next line:
|
205
217
|
#
|
@@ -242,6 +254,9 @@ require 'vips/gvalue'
|
|
242
254
|
# suffix. You can also write formatted images to memory buffers, or dump
|
243
255
|
# image data to a raw memory array.
|
244
256
|
#
|
257
|
+
# Use {Target} and {Image#write_to_target} to write formatted images to
|
258
|
+
# any data sink, for example URIs.
|
259
|
+
#
|
245
260
|
# # How it works
|
246
261
|
#
|
247
262
|
# The binding uses [ruby-ffi](https://github.com/ffi/ffi) to open the libvips
|
@@ -392,36 +407,132 @@ require 'vips/gvalue'
|
|
392
407
|
#
|
393
408
|
# # Automatic YARD documentation
|
394
409
|
#
|
395
|
-
# The bulk of these API docs are generated automatically by
|
396
|
-
#
|
397
|
-
#
|
398
|
-
# that that operation expects.
|
410
|
+
# The bulk of these API docs are generated automatically by {Yard#generate}.
|
411
|
+
# It examines libvips and writes a summary of each operation and the arguments
|
412
|
+
# and options that that operation expects.
|
399
413
|
#
|
400
|
-
# Use the [C API
|
401
|
-
# docs](https://jcupitt.github.io/libvips/API/current)
|
414
|
+
# Use the [C API # docs](https://libvips.github.io/libvips/API/current)
|
402
415
|
# for more detail.
|
403
416
|
#
|
404
417
|
# # Enums
|
405
418
|
#
|
406
419
|
# The libvips enums, such as `VipsBandFormat` appear in ruby-vips as Symbols
|
407
420
|
# like `:uchar`. They are documented as a set of classes for convenience, see
|
408
|
-
#
|
421
|
+
# {Vips::BandFormat}, for example.
|
409
422
|
#
|
410
423
|
# # Draw operations
|
411
424
|
#
|
412
|
-
#
|
413
|
-
#
|
414
|
-
#
|
415
|
-
#
|
425
|
+
# There are two ways of calling the libvips draw operations, like
|
426
|
+
# {Image#draw_circle} and {Image#draw_line}.
|
427
|
+
#
|
428
|
+
# First, you can use them like functions. For example:
|
429
|
+
#
|
430
|
+
# ```ruby
|
431
|
+
# y = x.draw_line 255, 0, 0, x.width, x.height
|
432
|
+
# ```
|
433
|
+
#
|
434
|
+
# This will make a new image, `y`, which is a copy of `x` but with a line
|
435
|
+
# drawn across it. `x` is unchanged.
|
436
|
+
#
|
437
|
+
# This is simple, but will be slow if you want to draw many lines, since
|
438
|
+
# ruby-vips will make a copy of the whole image each time.
|
439
|
+
#
|
440
|
+
# You can use {Image#mutate} to make a {MutableImage}. This is an image which
|
441
|
+
# is unshared and is only available inside the {Image#mutate} block. Within
|
442
|
+
# this block, you can use `!` versions of the draw operations to modify images
|
443
|
+
# and avoid the copy. For example:
|
444
|
+
#
|
445
|
+
# ```ruby
|
446
|
+
# image = image.mutate do |mutable|
|
447
|
+
# (0 ... 1).step(0.01) do |i|
|
448
|
+
# mutable.draw_line! 255, mutable.width * i, 0, 0, mutable.height * (1 - i)
|
449
|
+
# end
|
450
|
+
# end
|
451
|
+
# ```
|
452
|
+
#
|
453
|
+
# Now each {Image#draw_line} will directly modify the mutable image, saving
|
454
|
+
# the copy. This is much faster and needs much less memory.
|
455
|
+
#
|
456
|
+
# # Metadata read
|
457
|
+
#
|
458
|
+
# Use {Image#get_fields} to get a list of the metadata fields that an image
|
459
|
+
# supports. ICC profiles, for example, are in a field called
|
460
|
+
# `icc-profile-data`. Use `vipsheader -a something.jpg` at the command-line
|
461
|
+
# to see all the fields on an image.
|
462
|
+
#
|
463
|
+
# Use {Image#get_typeof} to get the type of a field. Types are integers, with
|
464
|
+
# 0 meaning "no such field". Constants like {GObject::GINT_TYPE} are useful for
|
465
|
+
# testing field types.
|
416
466
|
#
|
417
|
-
#
|
418
|
-
#
|
419
|
-
# make it inefficient. If you draw 100 lines on an image, for example, you'll
|
420
|
-
# copy the image 100 times. The wrapper does make sure that memory is recycled
|
421
|
-
# where possible, so you won't have 100 copies in memory.
|
467
|
+
# You can read image metadata using {Image#get}. The field value is converted
|
468
|
+
# to a Ruby value in the obvious way.
|
422
469
|
#
|
423
|
-
#
|
424
|
-
#
|
470
|
+
# # Metadata write
|
471
|
+
#
|
472
|
+
# You can also set and remove image metadata fields. Images are immutable, so
|
473
|
+
# you must make any changes inside a {Image#mutate} block. For example:
|
474
|
+
#
|
475
|
+
# ```ruby
|
476
|
+
# image = image.mutate do |mutable|
|
477
|
+
# image.get_fields.each do |field|
|
478
|
+
# mutable.remove! field unless field == "icc-profile-data"
|
479
|
+
# end
|
480
|
+
# end
|
481
|
+
# ```
|
482
|
+
#
|
483
|
+
# To remove all metadata except the icc profile.
|
484
|
+
#
|
485
|
+
# You can use {MutableImage#set!} to change the value of an existing field,
|
486
|
+
# and {MutableImage#set_type!} to create a new field with a specified type.
|
487
|
+
#
|
488
|
+
# # Progress
|
489
|
+
#
|
490
|
+
# You can attach signal handlers to images to watch computation progress. For
|
491
|
+
# example:
|
492
|
+
#
|
493
|
+
# ```ruby
|
494
|
+
# image = Vips::Image.black 1, 100000
|
495
|
+
# image.set_progress true
|
496
|
+
#
|
497
|
+
# def progress_to_s(name, progress)
|
498
|
+
# puts "#{name}:"
|
499
|
+
# puts " run = #{progress[:run]}"
|
500
|
+
# puts " eta = #{progress[:eta]}"
|
501
|
+
# puts " tpels = #{progress[:tpels]}"
|
502
|
+
# puts " npels = #{progress[:npels]}"
|
503
|
+
# puts " percent = #{progress[:percent]}"
|
504
|
+
# end
|
505
|
+
#
|
506
|
+
# image.signal_connect :preeval do |progress|
|
507
|
+
# progress_to_s("preeval", progress)
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# image.signal_connect :eval do |progress|
|
511
|
+
# progress_to_s("eval", progress)
|
512
|
+
# image.set_kill(true) if progress[:percent] > 50
|
513
|
+
# end
|
514
|
+
#
|
515
|
+
# image.signal_connect :posteval do |progress|
|
516
|
+
# progress_to_s("posteval", progress)
|
517
|
+
# end
|
518
|
+
#
|
519
|
+
# image.avg
|
520
|
+
# ```
|
521
|
+
#
|
522
|
+
# The `:eval` signal will fire for every tile that is processed. You can stop
|
523
|
+
# progress with {Image#set_kill} and processing will end with an exception.
|
524
|
+
#
|
525
|
+
# User streams
|
526
|
+
#
|
527
|
+
# You can make your own input and output stream objects with {SourceCustom} and
|
528
|
+
# {TargetCustom}. For example:
|
529
|
+
#
|
530
|
+
# ```ruby
|
531
|
+
# file = File.open "some/file", "rb"
|
532
|
+
# source = Vips::SourceCustom.new
|
533
|
+
# source.on_read { |length| file.read length }
|
534
|
+
# image = Vips::Image.new_from_source source, "", access: "sequential"
|
535
|
+
# ```
|
425
536
|
#
|
426
537
|
# # Overloads
|
427
538
|
#
|
@@ -459,16 +570,10 @@ require 'vips/gvalue'
|
|
459
570
|
module Vips
|
460
571
|
extend FFI::Library
|
461
572
|
|
462
|
-
|
463
|
-
vips_libname = 'libvips-42.dll'
|
464
|
-
else
|
465
|
-
vips_libname = 'vips'
|
466
|
-
end
|
467
|
-
|
468
|
-
ffi_lib vips_libname
|
573
|
+
ffi_lib library_name("vips", 42)
|
469
574
|
|
470
575
|
LOG_DOMAIN = "VIPS"
|
471
|
-
GLib
|
576
|
+
GLib.set_log_domain LOG_DOMAIN
|
472
577
|
|
473
578
|
typedef :ulong, :GType
|
474
579
|
|
@@ -482,9 +587,9 @@ module Vips
|
|
482
587
|
def initialize msg = nil
|
483
588
|
if msg
|
484
589
|
@details = msg
|
485
|
-
elsif Vips
|
486
|
-
@details = Vips
|
487
|
-
Vips
|
590
|
+
elsif Vips.vips_error_buffer != ""
|
591
|
+
@details = Vips.vips_error_buffer
|
592
|
+
Vips.vips_error_clear
|
488
593
|
else
|
489
594
|
@details = nil
|
490
595
|
end
|
@@ -494,7 +599,7 @@ module Vips
|
|
494
599
|
#
|
495
600
|
# @return [String] The error message
|
496
601
|
def to_s
|
497
|
-
if
|
602
|
+
if !@details.nil?
|
498
603
|
@details
|
499
604
|
else
|
500
605
|
super.to_s
|
@@ -504,8 +609,8 @@ module Vips
|
|
504
609
|
|
505
610
|
attach_function :vips_init, [:string], :int
|
506
611
|
|
507
|
-
if Vips
|
508
|
-
throw Vips
|
612
|
+
if Vips.vips_init($0) != 0
|
613
|
+
throw Vips.get_error
|
509
614
|
end
|
510
615
|
|
511
616
|
# don't use at_exit to call vips_shutdown, it causes problems with fork, and
|
@@ -569,7 +674,7 @@ module Vips
|
|
569
674
|
# Don't use this, instead change GLib::logger.level.
|
570
675
|
def self.set_debug debug
|
571
676
|
if debug
|
572
|
-
GLib
|
677
|
+
GLib.logger.level = Logger::DEBUG
|
573
678
|
end
|
574
679
|
end
|
575
680
|
|
@@ -591,30 +696,37 @@ module Vips
|
|
591
696
|
# vips_foreign_get_suffixes() was added in libvips 8.8
|
592
697
|
return [] unless Vips.respond_to? :vips_foreign_get_suffixes
|
593
698
|
|
594
|
-
array = Vips
|
699
|
+
array = Vips.vips_foreign_get_suffixes
|
595
700
|
|
596
701
|
names = []
|
597
702
|
p = array
|
598
703
|
until (q = p.read_pointer).null?
|
599
704
|
suff = q.read_string
|
600
|
-
GLib
|
705
|
+
GLib.g_free q
|
601
706
|
names << suff unless names.include? suff
|
602
707
|
p += FFI::Type::POINTER.size
|
603
708
|
end
|
604
|
-
GLib
|
709
|
+
GLib.g_free array
|
605
710
|
|
606
711
|
names
|
607
712
|
end
|
608
713
|
|
609
|
-
LIBRARY_VERSION = Vips
|
714
|
+
LIBRARY_VERSION = Vips.version_string
|
610
715
|
|
611
716
|
# libvips has this arbitrary number as a sanity-check upper bound on image
|
612
|
-
# size. It's sometimes useful
|
717
|
+
# size. It's sometimes useful to know when calculating scale factors.
|
613
718
|
MAX_COORD = 10000000
|
614
719
|
end
|
615
720
|
|
616
|
-
require
|
617
|
-
require
|
618
|
-
require
|
619
|
-
require
|
620
|
-
require
|
721
|
+
require "vips/object"
|
722
|
+
require "vips/operation"
|
723
|
+
require "vips/image"
|
724
|
+
require "vips/mutableimage"
|
725
|
+
require "vips/interpolate"
|
726
|
+
require "vips/region"
|
727
|
+
require "vips/version"
|
728
|
+
require "vips/connection"
|
729
|
+
require "vips/source"
|
730
|
+
require "vips/sourcecustom"
|
731
|
+
require "vips/target"
|
732
|
+
require "vips/targetcustom"
|