vips 8.8.3 → 8.11.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ # This module provides an interface to the top level bits of libvips
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+
9
+ module Vips
10
+ attach_function :vips_region_new, [:pointer], :pointer
11
+
12
+ if Vips::at_least_libvips?(8, 8)
13
+ attach_function :vips_region_fetch, [:pointer, :int, :int, :int, :int, SizeStruct.ptr], :pointer
14
+ attach_function :vips_region_width, [:pointer], :int
15
+ attach_function :vips_region_height, [:pointer], :int
16
+ end
17
+
18
+ # A region on an image. Create one, then use `fetch` to quickly get a region
19
+ # of pixels.
20
+ #
21
+ # For example:
22
+ #
23
+ # ```ruby
24
+ # region = Vips::Region.new(image)
25
+ # pixels = region.fetch(10, 10, 100, 100)
26
+ # ```
27
+ class Region < Vips::Object
28
+ # The layout of the VipsRegion struct.
29
+ module RegionLayout
30
+ def self.included(base)
31
+ base.class_eval do
32
+ layout :parent, Vips::Object::Struct
33
+ # rest opaque
34
+ end
35
+ end
36
+ end
37
+
38
+ class Struct < Vips::Object::Struct
39
+ include RegionLayout
40
+ end
41
+
42
+ class ManagedStruct < Vips::Object::ManagedStruct
43
+ include RegionLayout
44
+ end
45
+
46
+ def initialize(name)
47
+ ptr = Vips::vips_region_new name
48
+ raise Vips::Error if ptr.null?
49
+
50
+ super ptr
51
+ end
52
+
53
+ def width
54
+ Vips::vips_region_width self
55
+ end
56
+
57
+ def height
58
+ Vips::vips_region_height self
59
+ end
60
+
61
+ # Fetch a region filled with pixel data.
62
+ def fetch(left, top, width, height)
63
+ len = Vips::SizeStruct.new
64
+ ptr = Vips::vips_region_fetch self, left, top, width, height, len
65
+ raise Vips::Error if ptr.null?
66
+
67
+ # wrap up as an autopointer
68
+ ptr = FFI::AutoPointer.new(ptr, GLib::G_FREE)
69
+
70
+ ptr.get_bytes 0, len[:value]
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,89 @@
1
+ # This module provides an interface to the top level bits of libvips
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+
9
+ module Vips
10
+ if Vips::at_least_libvips?(8, 9)
11
+ attach_function :vips_source_new_from_descriptor, [:int], :pointer
12
+ attach_function :vips_source_new_from_file, [:pointer], :pointer
13
+ attach_function :vips_source_new_from_memory, [:pointer, :size_t], :pointer
14
+ end
15
+
16
+ # A source. For example:
17
+ #
18
+ # ```ruby
19
+ # source = Vips::Source.new_from_file("k2.jpg")
20
+ # image = Vips::Image.new_from_source(source)
21
+ # ```
22
+ class Source < Vips::Connection
23
+ module SourceLayout
24
+ def self.included(base)
25
+ base.class_eval do
26
+ layout :parent, Vips::Connection::Struct
27
+ # rest opaque
28
+ end
29
+ end
30
+ end
31
+
32
+ class Struct < Vips::Connection::Struct
33
+ include SourceLayout
34
+ end
35
+
36
+ class ManagedStruct < Vips::Connection::ManagedStruct
37
+ include SourceLayout
38
+ end
39
+
40
+ # Create a new source from a file descriptor. File descriptors are
41
+ # small integers, for example 0 is stdin.
42
+ #
43
+ # Pass sources to {Image.new_from_source} to load images from
44
+ # them.
45
+ #
46
+ # @param descriptor [Integer] the file descriptor
47
+ # @return [Source] the new Vips::Source
48
+ def self.new_from_descriptor(descriptor)
49
+ ptr = Vips::vips_source_new_from_descriptor descriptor
50
+ raise Vips::Error if ptr.null?
51
+
52
+ Vips::Source.new ptr
53
+ end
54
+
55
+ # Create a new source from a file name.
56
+ #
57
+ # Pass sources to {Image.new_from_source} to load images from
58
+ # them.
59
+ #
60
+ # @param filename [String] the name of the file
61
+ # @return [Source] the new Vips::Source
62
+ def self.new_from_file(filename)
63
+ raise Vips::Error, "filename is nil" if filename.nil?
64
+ ptr = Vips::vips_source_new_from_file filename
65
+ raise Vips::Error if ptr.null?
66
+
67
+ Vips::Source.new ptr
68
+ end
69
+
70
+ # Create a new source from an area of memory. Memory areas can be
71
+ # strings, arrays and so forth -- anything that supports bytesize.
72
+ #
73
+ # Pass sources to {Image.new_from_source} to load images from
74
+ # them.
75
+ #
76
+ # @param data [String] memory area
77
+ # @return [Source] the new Vips::Source
78
+ def self.new_from_memory(data)
79
+ ptr = Vips::vips_source_new_from_memory data, data.bytesize
80
+ raise Vips::Error if ptr.null?
81
+
82
+ # FIXME do we need to keep a ref to the underlying memory area? what
83
+ # about Image.new_from_buffer? Does that need a secret ref too?
84
+
85
+ Vips::Source.new ptr
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,90 @@
1
+ # This module provides an interface to the top level bits of libvips
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+
9
+ module Vips
10
+ if Vips::at_least_libvips?(8, 9)
11
+ attach_function :vips_source_custom_new, [], :pointer
12
+ end
13
+
14
+ # A source you can attach action signal handlers to to implement
15
+ # custom input types.
16
+ #
17
+ # For example:
18
+ #
19
+ # ```ruby
20
+ # file = File.open "some/file/name", "rb"
21
+ # source = Vips::SourceCustom.new
22
+ # source.on_read { |length| file.read length }
23
+ # image = Vips::Image.new_from_source source
24
+ # ```
25
+ #
26
+ # (just an example -- of course in practice you'd use {Source#new_from_file}
27
+ # to read from a named file)
28
+ class SourceCustom < Vips::Source
29
+ module SourceCustomLayout
30
+ def self.included(base)
31
+ base.class_eval do
32
+ layout :parent, Vips::Source::Struct
33
+ # rest opaque
34
+ end
35
+ end
36
+ end
37
+
38
+ class Struct < Vips::Source::Struct
39
+ include SourceCustomLayout
40
+ end
41
+
42
+ class ManagedStruct < Vips::Source::ManagedStruct
43
+ include SourceCustomLayout
44
+ end
45
+
46
+ def initialize
47
+ pointer = Vips::vips_source_custom_new
48
+ raise Vips::Error if pointer.null?
49
+
50
+ super pointer
51
+ end
52
+
53
+ # The block is executed to read data from the source. The interface is
54
+ # exactly as IO::read, ie. it takes a maximum number of bytes to read and
55
+ # returns a string of bytes from the source, or nil if the source is already
56
+ # at end of file.
57
+ #
58
+ # @yieldparam length [Integer] Read and return up to this many bytes
59
+ # @yieldreturn [String] Up to length bytes of data, or nil for EOF
60
+ def on_read &block
61
+ signal_connect "read" do |buf, len|
62
+ chunk = block.call len
63
+ return 0 if chunk == nil
64
+ bytes_read = chunk.bytesize
65
+ buf.put_bytes(0, chunk, 0, bytes_read)
66
+ chunk.clear
67
+
68
+ bytes_read
69
+ end
70
+ end
71
+
72
+ # The block is executed to seek the source. The interface is exactly as
73
+ # IO::seek, ie. it should take an offset and whence, and return the
74
+ # new read position.
75
+ #
76
+ # This handler is optional -- if you do not attach a seek handler,
77
+ # {Source} will treat your source like an unseekable pipe object and
78
+ # do extra caching.
79
+ #
80
+ # @yieldparam offset [Integer] Seek offset
81
+ # @yieldparam whence [Integer] Seek whence
82
+ # @yieldreturn [Integer] the new read position, or -1 on error
83
+ def on_seek &block
84
+ signal_connect "seek" do |offset, whence|
85
+ block.call offset, whence
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,87 @@
1
+ # This module provides an interface to the top level bits of libvips
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+
9
+ module Vips
10
+ if Vips::at_least_libvips?(8, 9)
11
+ attach_function :vips_target_new_to_descriptor, [:int], :pointer
12
+ attach_function :vips_target_new_to_file, [:string], :pointer
13
+ attach_function :vips_target_new_to_memory, [], :pointer
14
+ end
15
+
16
+ # A target. For example:
17
+ #
18
+ # ```ruby
19
+ # target = Vips::Target.new_to_file('k2.jpg')
20
+ # image.write_to_target(target, '.jpg')
21
+ # ```
22
+ class Target < Vips::Connection
23
+ # The layout of the VipsRegion struct.
24
+ module TargetLayout
25
+ def self.included(base)
26
+ base.class_eval do
27
+ layout :parent, Vips::Connection::Struct
28
+ # rest opaque
29
+ end
30
+ end
31
+ end
32
+
33
+ class Struct < Vips::Connection::Struct
34
+ include TargetLayout
35
+ end
36
+
37
+ class ManagedStruct < Vips::Connection::ManagedStruct
38
+ include TargetLayout
39
+ end
40
+
41
+ # Create a new target to a file descriptor. File descriptors are
42
+ # small integers, for example 1 is stdout.
43
+ #
44
+ # Pass targets to {Image#write_to_target} to write images to
45
+ # them.
46
+ #
47
+ # @param descriptor [Integer] the file descriptor
48
+ # @return [Target] the new Vips::Target
49
+ def self.new_to_descriptor(descriptor)
50
+ ptr = Vips::vips_target_new_to_descriptor descriptor
51
+ raise Vips::Error if ptr.null?
52
+
53
+ Vips::Target.new ptr
54
+ end
55
+
56
+ # Create a new target to a file name.
57
+ #
58
+ # Pass targets to {Image#write_to_target} to write images to
59
+ # them.
60
+ #
61
+ # @param filename [String] the name of the file
62
+ # @return [Target] the new Vips::Target
63
+ def self.new_to_file(filename)
64
+ raise Vips::Error, 'filename is nil' if filename.nil?
65
+ ptr = Vips::vips_target_new_to_file filename
66
+ raise Vips::Error if ptr.null?
67
+
68
+ Vips::Target.new ptr
69
+ end
70
+
71
+ # Create a new target to an area of memory.
72
+ #
73
+ # Pass targets to {Image#write_to_target} to write images to
74
+ # them.
75
+ #
76
+ # Once the image has been written, use {Object#get}`("blob")` to read out
77
+ # the data.
78
+ #
79
+ # @return [Target] the new Vips::Target
80
+ def self.new_to_memory
81
+ ptr = Vips::vips_target_new_to_memory
82
+
83
+ Vips::Target.new ptr
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,78 @@
1
+ # This module provides an interface to the top level bits of libvips
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+
9
+ module Vips
10
+ if Vips::at_least_libvips?(8, 9)
11
+ attach_function :vips_target_custom_new, [], :pointer
12
+ end
13
+
14
+ # A target you can attach action signal handlers to to implememt
15
+ # custom output types.
16
+ #
17
+ # For example:
18
+ #
19
+ # ```ruby
20
+ # file = File.open "some/file/name", "wb"
21
+ # target = Vips::TargetCustom.new
22
+ # target.on_write { |bytes| file.write bytes }
23
+ # image.write_to_target target, ".png"
24
+ # ```
25
+ #
26
+ # (just an example -- of course in practice you'd use {Target#new_to_file}
27
+ # to write to a named file)
28
+ class TargetCustom < Vips::Target
29
+ module TargetCustomLayout
30
+ def self.included(base)
31
+ base.class_eval do
32
+ layout :parent, Vips::Target::Struct
33
+ # rest opaque
34
+ end
35
+ end
36
+ end
37
+
38
+ class Struct < Vips::Target::Struct
39
+ include TargetCustomLayout
40
+ end
41
+
42
+ class ManagedStruct < Vips::Target::ManagedStruct
43
+ include TargetCustomLayout
44
+ end
45
+
46
+ def initialize
47
+ pointer = Vips::vips_target_custom_new
48
+ raise Vips::Error if pointer.null?
49
+
50
+ super pointer
51
+ end
52
+
53
+ # The block is executed to write data to the source. The interface is
54
+ # exactly as IO::write, ie. it should write the string and return the
55
+ # number of bytes written.
56
+ #
57
+ # @yieldparam bytes [String] Write these bytes to the file
58
+ # @yieldreturn [Integer] The number of bytes written, or -1 on error
59
+ def on_write &block
60
+ signal_connect "write" do |p, len|
61
+ chunk = p.get_bytes(0, len)
62
+ bytes_written = block.call chunk
63
+ chunk.clear
64
+
65
+ bytes_written
66
+ end
67
+ end
68
+
69
+ # The block is executed at the end of write. It should do any necessary
70
+ # finishing action, such as closing a file.
71
+ def on_finish &block
72
+ signal_connect "finish" do
73
+ block.call()
74
+ end
75
+ end
76
+
77
+ end
78
+ end
data/lib/vips/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Vips
3
- VERSION = "8.8.3"
3
+ VERSION = "8.11.3"
4
4
  end
data/lib/vips.rb CHANGED
@@ -10,6 +10,29 @@ require 'logger'
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
@@ -19,13 +42,7 @@ module GLib
19
42
 
20
43
  extend FFI::Library
21
44
 
22
- if FFI::Platform.windows?
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
 
@@ -117,13 +134,7 @@ end
117
134
  module GObject
118
135
  extend FFI::Library
119
136
 
120
- if FFI::Platform.windows?
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
@@ -155,7 +166,7 @@ require 'vips/gobject'
155
166
  require 'vips/gvalue'
156
167
 
157
168
  # This module provides a binding for the [libvips image processing
158
- # library](https://jcupitt.github.io/libvips/).
169
+ # library](https://libvips.github.io/libvips/).
159
170
  #
160
171
  # # Example
161
172
  #
@@ -201,6 +212,9 @@ require 'vips/gvalue'
201
212
  # memory buffers, create images that wrap C-style memory arrays, or make images
202
213
  # from constants.
203
214
  #
215
+ # Use {Source} and {Image.new_from_source} to load images from any data
216
+ # source, for example URIs.
217
+ #
204
218
  # The next line:
205
219
  #
206
220
  # ```ruby
@@ -242,6 +256,9 @@ require 'vips/gvalue'
242
256
  # suffix. You can also write formatted images to memory buffers, or dump
243
257
  # image data to a raw memory array.
244
258
  #
259
+ # Use {Target} and {Image#write_to_target} to write formatted images to
260
+ # any data sink, for example URIs.
261
+ #
245
262
  # # How it works
246
263
  #
247
264
  # The binding uses [ruby-ffi](https://github.com/ffi/ffi) to open the libvips
@@ -393,12 +410,12 @@ require 'vips/gvalue'
393
410
  # # Automatic YARD documentation
394
411
  #
395
412
  # The bulk of these API docs are generated automatically by
396
- # {Vips::generate_yard}. It examines
413
+ # {Vips::Yard::generate}. It examines
397
414
  # libvips and writes a summary of each operation and the arguments and options
398
415
  # that that operation expects.
399
416
  #
400
417
  # Use the [C API
401
- # docs](https://jcupitt.github.io/libvips/API/current)
418
+ # docs](https://libvips.github.io/libvips/API/current)
402
419
  # for more detail.
403
420
  #
404
421
  # # Enums
@@ -423,6 +440,55 @@ require 'vips/gvalue'
423
440
  # If you want to avoid the copies, you'll need to call drawing operations
424
441
  # yourself.
425
442
  #
443
+ # # Progress
444
+ #
445
+ # You can attach signal handlers to images to watch computation progress. For
446
+ # example:
447
+ #
448
+ # ```ruby
449
+ # image = Vips::Image.black 1, 100000
450
+ # image.set_progress true
451
+ #
452
+ # def progress_to_s(name, progress)
453
+ # puts "#{name}:"
454
+ # puts " run = #{progress[:run]}"
455
+ # puts " eta = #{progress[:eta]}"
456
+ # puts " tpels = #{progress[:tpels]}"
457
+ # puts " npels = #{progress[:npels]}"
458
+ # puts " percent = #{progress[:percent]}"
459
+ # end
460
+ #
461
+ # image.signal_connect :preeval do |progress|
462
+ # progress_to_s("preeval", progress)
463
+ # end
464
+ #
465
+ # image.signal_connect :eval do |progress|
466
+ # progress_to_s("eval", progress)
467
+ # image.set_kill(true) if progress[:percent] > 50
468
+ # end
469
+ #
470
+ # image.signal_connect :posteval do |progress|
471
+ # progress_to_s("posteval", progress)
472
+ # end
473
+ #
474
+ # image.avg
475
+ # ```
476
+ #
477
+ # The `:eval` signal will fire for every tile that is processed. You can stop
478
+ # progress with {Image#set_kill} and processing will end with an exception.
479
+ #
480
+ # User streams
481
+ #
482
+ # You can make your own input and output stream objects with {SourceCustom} and
483
+ # {TargetCustom}. For example:
484
+ #
485
+ # ```ruby
486
+ # file = File.open "some/file", "rb"
487
+ # source = Vips::SourceCustom.new
488
+ # source.on_read { |length| file.read length }
489
+ # image = Vips::Image.new_from_source source, "", access: "sequential"
490
+ # ```
491
+ #
426
492
  # # Overloads
427
493
  #
428
494
  # The wrapper defines the usual set of arithmetic, boolean and relational
@@ -462,7 +528,7 @@ module Vips
462
528
  if FFI::Platform.windows?
463
529
  vips_libname = 'libvips-42.dll'
464
530
  else
465
- vips_libname = File.expand_path(FFI::map_library_name('vips'), __dir__)
531
+ vips_libname = File.expand_path(FFI.map_library_name('vips'), __dir__)
466
532
  end
467
533
 
468
534
  ffi_lib vips_libname
@@ -609,7 +675,7 @@ module Vips
609
675
  LIBRARY_VERSION = Vips::version_string
610
676
 
611
677
  # libvips has this arbitrary number as a sanity-check upper bound on image
612
- # size. It's sometimes useful for know whan calculating image ratios.
678
+ # size. It's sometimes useful to know when calculating scale factors.
613
679
  MAX_COORD = 10000000
614
680
  end
615
681
 
@@ -617,4 +683,10 @@ require 'vips/object'
617
683
  require 'vips/operation'
618
684
  require 'vips/image'
619
685
  require 'vips/interpolate'
686
+ require 'vips/region'
620
687
  require 'vips/version'
688
+ require 'vips/connection'
689
+ require 'vips/source'
690
+ require 'vips/sourcecustom'
691
+ require 'vips/target'
692
+ require 'vips/targetcustom'