ruby-vips 2.0.16 → 2.0.17
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/.rubocop_todo.yml +1 -1
- data/.travis.yml +1 -6
- data/CHANGELOG.md +11 -0
- data/README.md +38 -37
- data/TODO +1 -1
- data/VERSION +1 -1
- data/example/connection.rb +17 -0
- data/example/progress.rb +30 -0
- data/lib/vips.rb +64 -4
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/gobject.rb +9 -1
- data/lib/vips/gvalue.rb +13 -4
- data/lib/vips/image.rb +213 -112
- data/lib/vips/methods.rb +330 -40
- data/lib/vips/object.rb +123 -5
- data/lib/vips/operation.rb +156 -80
- data/lib/vips/region.rb +2 -2
- data/lib/vips/source.rb +89 -0
- data/lib/vips/sourcecustom.rb +90 -0
- data/lib/vips/target.rb +87 -0
- data/lib/vips/targetcustom.rb +78 -0
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +3 -1
- metadata +14 -6
data/lib/vips/image.rb
CHANGED
@@ -14,6 +14,9 @@ module Vips
|
|
14
14
|
|
15
15
|
attach_function :vips_image_copy_memory, [:pointer], :pointer
|
16
16
|
|
17
|
+
attach_function :vips_image_set_progress, [:pointer, :bool], :void
|
18
|
+
attach_function :vips_image_set_kill, [:pointer, :bool], :void
|
19
|
+
|
17
20
|
attach_function :vips_filename_get_filename, [:string], :pointer
|
18
21
|
attach_function :vips_filename_get_options, [:string], :pointer
|
19
22
|
|
@@ -22,6 +25,11 @@ module Vips
|
|
22
25
|
attach_function :vips_foreign_find_load_buffer, [:pointer, :size_t], :string
|
23
26
|
attach_function :vips_foreign_find_save_buffer, [:string], :string
|
24
27
|
|
28
|
+
if Vips::at_least_libvips?(8, 9)
|
29
|
+
attach_function :vips_foreign_find_load_source, [:pointer], :string
|
30
|
+
attach_function :vips_foreign_find_save_target, [:string], :string
|
31
|
+
end
|
32
|
+
|
25
33
|
attach_function :vips_image_write_to_memory,
|
26
34
|
[:pointer, SizeStruct.ptr], :pointer
|
27
35
|
|
@@ -109,7 +117,7 @@ module Vips
|
|
109
117
|
|
110
118
|
unless Image::complex? image.format
|
111
119
|
if image.bands % 2 != 0
|
112
|
-
raise Error, "not an even number of bands"
|
120
|
+
raise Vips::Error, "not an even number of bands"
|
113
121
|
end
|
114
122
|
|
115
123
|
unless Image::float? image.format
|
@@ -290,11 +298,50 @@ module Vips
|
|
290
298
|
# @return [Image] the loaded image
|
291
299
|
def self.new_from_buffer data, option_string, **opts
|
292
300
|
loader = Vips::vips_foreign_find_load_buffer data, data.bytesize
|
293
|
-
raise Vips::Error if loader
|
301
|
+
raise Vips::Error if loader.nil?
|
294
302
|
|
295
303
|
Vips::Operation.call loader, [data], opts, option_string
|
296
304
|
end
|
297
305
|
|
306
|
+
# Create a new {Image} from a source. Load options may be passed as
|
307
|
+
# strings or appended as a hash. For example:
|
308
|
+
#
|
309
|
+
# ```
|
310
|
+
# source = Vips::Source.new_from_file("k2.jpg")
|
311
|
+
# image = Vips::Image.new_from_source source, "shrink=2"
|
312
|
+
# ```
|
313
|
+
#
|
314
|
+
# or alternatively:
|
315
|
+
#
|
316
|
+
# ```
|
317
|
+
# image = Vips::Image.new_from_source source, "", shrink: 2
|
318
|
+
# ```
|
319
|
+
#
|
320
|
+
# The options available depend on the file format. Try something like:
|
321
|
+
#
|
322
|
+
# ```
|
323
|
+
# $ vips jpegload_source
|
324
|
+
# ```
|
325
|
+
#
|
326
|
+
# at the command-line to see the available options. Not all loaders
|
327
|
+
# support load from source, but at least JPEG, PNG and
|
328
|
+
# TIFF images will work.
|
329
|
+
#
|
330
|
+
# Loading is fast: only enough data is read to be able to fill
|
331
|
+
# out the header. Pixels will only be read and decompressed when they are
|
332
|
+
# needed.
|
333
|
+
#
|
334
|
+
# @param source [Vips::Source] the source to load from
|
335
|
+
# @param option_string [String] load options as a string
|
336
|
+
# @macro vips.loadopts
|
337
|
+
# @return [Image] the loaded image
|
338
|
+
def self.new_from_source source, option_string, **opts
|
339
|
+
loader = Vips::vips_foreign_find_load_source source
|
340
|
+
raise Vips::Error if loader.nil?
|
341
|
+
|
342
|
+
Vips::Operation.call loader, [source], opts, option_string
|
343
|
+
end
|
344
|
+
|
298
345
|
def self.matrix_from_array width, height, array
|
299
346
|
ptr = FFI::MemoryPointer.new :double, array.length
|
300
347
|
ptr.write_array_of_double array
|
@@ -454,7 +501,7 @@ module Vips
|
|
454
501
|
option_string = Vips::p2str(Vips::vips_filename_get_options format_string)
|
455
502
|
saver = Vips::vips_foreign_find_save_buffer filename
|
456
503
|
if saver == nil
|
457
|
-
raise Vips::Error, "No known saver for '#{filename}'."
|
504
|
+
raise Vips::Error, "No known buffer saver for '#{filename}'."
|
458
505
|
end
|
459
506
|
|
460
507
|
buffer = Vips::Operation.call saver, [self], opts, option_string
|
@@ -465,6 +512,44 @@ module Vips
|
|
465
512
|
return buffer
|
466
513
|
end
|
467
514
|
|
515
|
+
# Write this image to a target. Save options may be encoded in
|
516
|
+
# the format_string or given as a hash. For example:
|
517
|
+
#
|
518
|
+
# ```ruby
|
519
|
+
# target = Vips::Target.new_to_file "k2.jpg"
|
520
|
+
# image.write_to_target target, ".jpg[Q=90]"
|
521
|
+
# ```
|
522
|
+
#
|
523
|
+
# or equivalently:
|
524
|
+
#
|
525
|
+
# ```ruby
|
526
|
+
# image.write_to_target target, ".jpg", Q: 90
|
527
|
+
# ```
|
528
|
+
#
|
529
|
+
# The full set of save options depend on the selected saver. Try
|
530
|
+
# something like:
|
531
|
+
#
|
532
|
+
# ```
|
533
|
+
# $ vips jpegsave_target
|
534
|
+
# ```
|
535
|
+
#
|
536
|
+
# to see all the available options for JPEG save.
|
537
|
+
#
|
538
|
+
# @param target [Vips::Target] the target to write to
|
539
|
+
# @param format_string [String] save format plus string options
|
540
|
+
# @macro vips.saveopts
|
541
|
+
def write_to_target target, format_string, **opts
|
542
|
+
filename = Vips::p2str(Vips::vips_filename_get_filename format_string)
|
543
|
+
option_string = Vips::p2str(Vips::vips_filename_get_options format_string)
|
544
|
+
saver = Vips::vips_foreign_find_save_target filename
|
545
|
+
if saver == nil
|
546
|
+
raise Vips::Error, "No known target saver for '#{filename}'."
|
547
|
+
end
|
548
|
+
|
549
|
+
Vips::Operation.call saver, [self, target], opts, option_string
|
550
|
+
write_gc
|
551
|
+
end
|
552
|
+
|
468
553
|
# Write this image to a large memory buffer.
|
469
554
|
#
|
470
555
|
# @return [String] the pixels as a huge binary string
|
@@ -479,6 +564,28 @@ module Vips
|
|
479
564
|
ptr.get_bytes 0, len[:value]
|
480
565
|
end
|
481
566
|
|
567
|
+
# Turn progress signalling on and off.
|
568
|
+
#
|
569
|
+
# If this is on, the most-downstream image from this image will issue
|
570
|
+
# progress signals.
|
571
|
+
#
|
572
|
+
# @see Object#signal_connect
|
573
|
+
# @param state [Boolean] progress signalling state
|
574
|
+
def set_progress state
|
575
|
+
Vips::vips_image_set_progress self, state
|
576
|
+
end
|
577
|
+
|
578
|
+
# Kill computation of this time.
|
579
|
+
#
|
580
|
+
# Set true to stop computation of this image. You can call this from a
|
581
|
+
# progress handler, for example.
|
582
|
+
#
|
583
|
+
# @see Object#signal_connect
|
584
|
+
# @param kill [Boolean] stop computation
|
585
|
+
def set_kill kill
|
586
|
+
Vips::vips_image_set_kill self, kill
|
587
|
+
end
|
588
|
+
|
482
589
|
# Get the `GType` of a metadata field. The result is 0 if no such field
|
483
590
|
# exists.
|
484
591
|
#
|
@@ -517,10 +624,11 @@ module Vips
|
|
517
624
|
end
|
518
625
|
|
519
626
|
gvalue = GObject::GValue.alloc
|
520
|
-
|
521
|
-
|
627
|
+
raise Vips::Error if Vips::vips_image_get(self, name, gvalue) != 0
|
628
|
+
result = gvalue.get
|
629
|
+
gvalue.unset
|
522
630
|
|
523
|
-
|
631
|
+
result
|
524
632
|
end
|
525
633
|
|
526
634
|
# Get the names of all fields on an image. Use this to loop over all
|
@@ -565,6 +673,7 @@ module Vips
|
|
565
673
|
gvalue.init gtype
|
566
674
|
gvalue.set value
|
567
675
|
Vips::vips_image_set self, name, gvalue
|
676
|
+
gvalue.unset
|
568
677
|
end
|
569
678
|
|
570
679
|
# Set the value of a metadata item on an image. The metadata item must
|
@@ -1065,7 +1174,7 @@ module Vips
|
|
1065
1174
|
GObject::GValue.from_nick Vips::BLEND_MODE_TYPE, x
|
1066
1175
|
end
|
1067
1176
|
|
1068
|
-
Vips::Image.composite([self] + overlay, mode, opts)
|
1177
|
+
Vips::Image.composite([self] + overlay, mode, **opts)
|
1069
1178
|
end
|
1070
1179
|
|
1071
1180
|
# Return the coordinates of the image maximum.
|
@@ -1315,29 +1424,26 @@ module Vips
|
|
1315
1424
|
# @param opts [Hash] Set of options
|
1316
1425
|
# @return [Vips::Image] Output image
|
1317
1426
|
def scaleimage **opts
|
1318
|
-
Vips::Image.scale self, opts
|
1427
|
+
Vips::Image.scale self, **opts
|
1319
1428
|
end
|
1320
1429
|
end
|
1321
1430
|
end
|
1322
1431
|
|
1323
1432
|
module Vips
|
1324
|
-
# This
|
1433
|
+
# This module generates yard comments for all the dynamically bound
|
1325
1434
|
# vips operations.
|
1326
1435
|
#
|
1327
1436
|
# Regenerate with something like:
|
1328
1437
|
#
|
1329
1438
|
# ```
|
1330
1439
|
# $ ruby > methods.rb
|
1331
|
-
# require 'vips'; Vips::
|
1440
|
+
# require 'vips'; Vips::Yard.generate
|
1332
1441
|
# ^D
|
1333
1442
|
# ```
|
1334
1443
|
|
1335
|
-
|
1336
|
-
# these have hand-written methods, see above
|
1337
|
-
no_generate = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1338
|
-
|
1444
|
+
module Yard
|
1339
1445
|
# map gobject's type names to Ruby
|
1340
|
-
|
1446
|
+
MAP_GO_TO_RUBY = {
|
1341
1447
|
"gboolean" => "Boolean",
|
1342
1448
|
"gint" => "Integer",
|
1343
1449
|
"gdouble" => "Float",
|
@@ -1345,116 +1451,99 @@ module Vips
|
|
1345
1451
|
"gchararray" => "String",
|
1346
1452
|
"VipsImage" => "Vips::Image",
|
1347
1453
|
"VipsInterpolate" => "Vips::Interpolate",
|
1454
|
+
"VipsConnection" => "Vips::Connection",
|
1455
|
+
"VipsSource" => "Vips::Source",
|
1456
|
+
"VipsTarget" => "Vips::Target",
|
1457
|
+
"VipsSourceCustom" => "Vips::SourceCustom",
|
1458
|
+
"VipsTargetCustom" => "Vips::TargetCustom",
|
1348
1459
|
"VipsArrayDouble" => "Array<Double>",
|
1349
1460
|
"VipsArrayInt" => "Array<Integer>",
|
1350
1461
|
"VipsArrayImage" => "Array<Image>",
|
1351
1462
|
"VipsArrayString" => "Array<String>",
|
1352
1463
|
}
|
1353
1464
|
|
1354
|
-
|
1355
|
-
|
1356
|
-
return if (op_flags & OPERATION_DEPRECATED) != 0
|
1357
|
-
return if no_generate.include? nickname
|
1358
|
-
|
1359
|
-
description = Vips::vips_object_get_description op
|
1360
|
-
|
1361
|
-
# find and classify all the arguments the operator can take
|
1362
|
-
required_input = []
|
1363
|
-
optional_input = []
|
1364
|
-
required_output = []
|
1365
|
-
optional_output = []
|
1366
|
-
member_x = nil
|
1367
|
-
op.argument_map do |pspec, argument_class, _argument_instance|
|
1368
|
-
arg_flags = argument_class[:flags]
|
1369
|
-
next if (arg_flags & ARGUMENT_CONSTRUCT) == 0
|
1370
|
-
next if (arg_flags & ARGUMENT_DEPRECATED) != 0
|
1371
|
-
|
1372
|
-
name = pspec[:name].tr("-", "_")
|
1373
|
-
# 'in' as a param name confuses yard
|
1374
|
-
name = "im" if name == "in"
|
1375
|
-
gtype = pspec[:value_type]
|
1376
|
-
fundamental = GObject::g_type_fundamental gtype
|
1377
|
-
type_name = GObject::g_type_name gtype
|
1378
|
-
if map_go_to_ruby.include? type_name
|
1379
|
-
type_name = map_go_to_ruby[type_name]
|
1380
|
-
end
|
1381
|
-
if fundamental == GObject::GFLAGS_TYPE ||
|
1382
|
-
fundamental == GObject::GENUM_TYPE
|
1383
|
-
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1384
|
-
end
|
1385
|
-
blurb = GObject::g_param_spec_get_blurb pspec
|
1386
|
-
value = {
|
1387
|
-
name: name,
|
1388
|
-
flags: arg_flags,
|
1389
|
-
gtype: gtype,
|
1390
|
-
type_name: type_name,
|
1391
|
-
blurb: blurb
|
1392
|
-
}
|
1393
|
-
|
1394
|
-
if (arg_flags & ARGUMENT_INPUT) != 0
|
1395
|
-
if (arg_flags & ARGUMENT_REQUIRED) != 0
|
1396
|
-
# note the first required input image, if any ... we
|
1397
|
-
# will be a method of this instance
|
1398
|
-
if !member_x && gtype == Vips::IMAGE_TYPE
|
1399
|
-
member_x = value
|
1400
|
-
else
|
1401
|
-
required_input << value
|
1402
|
-
end
|
1403
|
-
else
|
1404
|
-
optional_input << value
|
1405
|
-
end
|
1406
|
-
end
|
1465
|
+
# these have hand-written methods, see above
|
1466
|
+
NO_GENERATE = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1407
1467
|
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1468
|
+
# these are aliased (appear under several names)
|
1469
|
+
ALIAS = ["crop"]
|
1470
|
+
|
1471
|
+
# turn a gtype into a ruby type name
|
1472
|
+
def self.gtype_to_ruby gtype
|
1473
|
+
fundamental = GObject::g_type_fundamental gtype
|
1474
|
+
type_name = GObject::g_type_name gtype
|
1475
|
+
|
1476
|
+
if MAP_GO_TO_RUBY.include? type_name
|
1477
|
+
type_name = MAP_GO_TO_RUBY[type_name]
|
1478
|
+
end
|
1479
|
+
|
1480
|
+
if fundamental == GObject::GFLAGS_TYPE ||
|
1481
|
+
fundamental == GObject::GENUM_TYPE
|
1482
|
+
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1418
1483
|
end
|
1419
1484
|
|
1485
|
+
type_name
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
def self.generate_operation introspect
|
1489
|
+
return if (introspect.flags & OPERATION_DEPRECATED) != 0
|
1490
|
+
return if NO_GENERATE.include? introspect.name
|
1491
|
+
|
1492
|
+
method_args = introspect.method_args
|
1493
|
+
required_output = introspect.required_output
|
1494
|
+
optional_input = introspect.optional_input
|
1495
|
+
optional_output = introspect.optional_output
|
1496
|
+
|
1420
1497
|
print "# @!method "
|
1421
|
-
print "self." unless member_x
|
1422
|
-
print "#{
|
1423
|
-
print
|
1424
|
-
print ", " if
|
1498
|
+
print "self." unless introspect.member_x
|
1499
|
+
print "#{introspect.name}("
|
1500
|
+
print method_args.map{ |x| x[:yard_name] }.join(", ")
|
1501
|
+
print ", " if method_args.length > 0
|
1425
1502
|
puts "**opts)"
|
1426
1503
|
|
1427
|
-
puts "# #{description.capitalize}."
|
1504
|
+
puts "# #{introspect.description.capitalize}."
|
1505
|
+
|
1506
|
+
method_args.each do |details|
|
1507
|
+
yard_name = details[:yard_name]
|
1508
|
+
gtype = details[:gtype]
|
1509
|
+
blurb = details[:blurb]
|
1428
1510
|
|
1429
|
-
|
1430
|
-
puts "# @param #{arg[:name]} [#{arg[:type_name]}] #{arg[:blurb]}"
|
1511
|
+
puts "# @param #{yard_name} [#{gtype_to_ruby(gtype)}] #{blurb}"
|
1431
1512
|
end
|
1432
1513
|
|
1433
1514
|
puts "# @param opts [Hash] Set of options"
|
1434
|
-
optional_input.each do |
|
1435
|
-
|
1436
|
-
|
1515
|
+
optional_input.each do |arg_name, details|
|
1516
|
+
yard_name = details[:yard_name]
|
1517
|
+
gtype = details[:gtype]
|
1518
|
+
blurb = details[:blurb]
|
1519
|
+
|
1520
|
+
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} " +
|
1521
|
+
"#{blurb}"
|
1437
1522
|
end
|
1438
|
-
optional_output.each do |
|
1439
|
-
|
1440
|
-
|
1523
|
+
optional_output.each do |arg_name, details|
|
1524
|
+
yard_name = details[:yard_name]
|
1525
|
+
gtype = details[:gtype]
|
1526
|
+
blurb = details[:blurb]
|
1527
|
+
|
1528
|
+
print "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name}"
|
1529
|
+
puts " Output #{blurb}"
|
1441
1530
|
end
|
1442
1531
|
|
1443
1532
|
print "# @return ["
|
1444
1533
|
if required_output.length == 0
|
1445
1534
|
print "nil"
|
1446
1535
|
elsif required_output.length == 1
|
1447
|
-
print required_output.first[:
|
1536
|
+
print gtype_to_ruby(required_output.first[:gtype])
|
1448
1537
|
else
|
1449
1538
|
print "Array<"
|
1450
|
-
print required_output.map
|
1539
|
+
print required_output.map{ |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1451
1540
|
print ">"
|
1452
1541
|
end
|
1453
1542
|
if optional_output.length > 0
|
1454
1543
|
print ", Hash<Symbol => Object>"
|
1455
1544
|
end
|
1456
1545
|
print "] "
|
1457
|
-
print required_output.map
|
1546
|
+
print required_output.map{ |x| x[:blurb] }.join(", ")
|
1458
1547
|
if optional_output.length > 0
|
1459
1548
|
print ", " if required_output.length > 0
|
1460
1549
|
print "Hash of optional output items"
|
@@ -1464,30 +1553,42 @@ module Vips
|
|
1464
1553
|
puts ""
|
1465
1554
|
end
|
1466
1555
|
|
1467
|
-
|
1468
|
-
|
1556
|
+
def self.generate
|
1557
|
+
alias_gtypes = {}
|
1558
|
+
ALIAS.each do |name|
|
1559
|
+
gtype = Vips::type_find "VipsOperation", name
|
1560
|
+
alias_gtypes[gtype] = name
|
1561
|
+
end
|
1469
1562
|
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
nil
|
1563
|
+
generate_class = lambda do |gtype, _|
|
1564
|
+
if alias_gtypes.key? gtype
|
1565
|
+
name = alias_gtypes[gtype]
|
1566
|
+
else
|
1567
|
+
name = Vips::nickname_find gtype
|
1476
1568
|
end
|
1477
1569
|
|
1478
|
-
|
1479
|
-
|
1570
|
+
if name
|
1571
|
+
begin
|
1572
|
+
# can fail for abstract types
|
1573
|
+
introspect = Vips::Introspect.get_yard name
|
1574
|
+
rescue Vips::Error
|
1575
|
+
nil
|
1576
|
+
end
|
1480
1577
|
|
1481
|
-
|
1482
|
-
|
1578
|
+
generate_operation(introspect) if introspect
|
1579
|
+
end
|
1483
1580
|
|
1484
|
-
|
1485
|
-
|
1486
|
-
puts ""
|
1581
|
+
Vips::vips_type_map gtype, generate_class, nil
|
1582
|
+
end
|
1487
1583
|
|
1488
|
-
|
1584
|
+
puts "module Vips"
|
1585
|
+
puts " class Image"
|
1586
|
+
puts ""
|
1489
1587
|
|
1490
|
-
|
1491
|
-
|
1588
|
+
generate_class.(GObject::g_type_from_name("VipsOperation"), nil)
|
1589
|
+
|
1590
|
+
puts " end"
|
1591
|
+
puts "end"
|
1592
|
+
end
|
1492
1593
|
end
|
1493
1594
|
end
|