ruby-vips 0.3.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +22 -0
  3. data/CHANGELOG.md +4 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +46 -31
  6. data/{LICENSE → LICENSE.txt} +1 -1
  7. data/README.md +101 -145
  8. data/Rakefile +45 -0
  9. data/TODO +8 -32
  10. data/VERSION +1 -0
  11. data/example/annotate.rb +17 -0
  12. data/example/daltonize8.rb +75 -0
  13. data/example/example1.rb +84 -0
  14. data/example/example2.rb +31 -0
  15. data/example/example3.rb +19 -0
  16. data/example/example4.rb +18 -0
  17. data/example/example5.rb +31 -0
  18. data/example/trim8.rb +41 -0
  19. data/example/watermark.rb +44 -0
  20. data/example/wobble.rb +36 -0
  21. data/lib/vips.rb +151 -14
  22. data/lib/vips/access.rb +14 -0
  23. data/lib/vips/align.rb +11 -0
  24. data/lib/vips/angle.rb +12 -0
  25. data/lib/vips/angle45.rb +16 -0
  26. data/lib/vips/argument.rb +163 -0
  27. data/lib/vips/bandformat.rb +20 -0
  28. data/lib/vips/call.rb +302 -0
  29. data/lib/vips/coding.rb +14 -0
  30. data/lib/vips/demandstyle.rb +35 -0
  31. data/lib/vips/direction.rb +11 -0
  32. data/lib/vips/error.rb +30 -0
  33. data/lib/vips/extend.rb +22 -0
  34. data/lib/vips/foreignflags.rb +20 -0
  35. data/lib/vips/image.rb +1382 -0
  36. data/lib/vips/interpolate.rb +37 -0
  37. data/lib/vips/interpretation.rb +28 -0
  38. data/lib/vips/methods.rb +1807 -0
  39. data/lib/vips/operation.rb +19 -0
  40. data/ruby-vips8.gemspec +112 -0
  41. data/spec/image_spec.rb +515 -0
  42. data/spec/samples/balloon.v +0 -0
  43. data/spec/samples/ghost.ppm +405 -0
  44. data/spec/samples/huge.jpg +0 -0
  45. data/spec/samples/icc.jpg +0 -0
  46. data/spec/samples/lcd.icc +0 -0
  47. data/spec/samples/lion.svg +154 -0
  48. data/spec/samples/sample.csv +7 -0
  49. data/spec/samples/sample.exr +0 -0
  50. data/spec/samples/wagon.jpg +0 -0
  51. data/spec/samples/wagon.v +0 -0
  52. data/spec/spec_helper.rb +49 -0
  53. data/spec/vips_spec.rb +74 -0
  54. metadata +110 -70
  55. data/ext/extconf.rb +0 -31
  56. data/ext/header.c +0 -457
  57. data/ext/header.h +0 -9
  58. data/ext/image.c +0 -629
  59. data/ext/image.h +0 -72
  60. data/ext/image_arithmetic.c +0 -936
  61. data/ext/image_arithmetic.h +0 -38
  62. data/ext/image_boolean.c +0 -301
  63. data/ext/image_boolean.h +0 -8
  64. data/ext/image_colour.c +0 -590
  65. data/ext/image_colour.h +0 -36
  66. data/ext/image_conversion.c +0 -884
  67. data/ext/image_conversion.h +0 -38
  68. data/ext/image_convolution.c +0 -368
  69. data/ext/image_convolution.h +0 -13
  70. data/ext/image_freq_filt.c +0 -740
  71. data/ext/image_freq_filt.h +0 -27
  72. data/ext/image_histograms_lut.c +0 -643
  73. data/ext/image_histograms_lut.h +0 -28
  74. data/ext/image_morphology.c +0 -327
  75. data/ext/image_morphology.h +0 -13
  76. data/ext/image_mosaicing.c +0 -554
  77. data/ext/image_mosaicing.h +0 -15
  78. data/ext/image_relational.c +0 -384
  79. data/ext/image_relational.h +0 -8
  80. data/ext/image_resample.c +0 -249
  81. data/ext/image_resample.h +0 -9
  82. data/ext/interpolator.c +0 -106
  83. data/ext/interpolator.h +0 -7
  84. data/ext/mask.c +0 -347
  85. data/ext/mask.h +0 -18
  86. data/ext/reader.c +0 -261
  87. data/ext/reader.h +0 -2
  88. data/ext/ruby_vips.c +0 -188
  89. data/ext/ruby_vips.h +0 -72
  90. data/ext/tags +0 -450
  91. data/ext/writer.c +0 -371
  92. data/ext/writer.h +0 -2
  93. data/lib/vips/reader.rb +0 -272
  94. data/lib/vips/version.rb +0 -3
  95. data/lib/vips/writer.rb +0 -342
  96. data/ruby-vips.gemspec +0 -100
  97. data/ruby.supp +0 -134
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+
16
+ require 'jeweler'
17
+
18
+ Jeweler::Tasks.new do |gem|
19
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
20
+ gem.name = "ruby-vips"
21
+ gem.homepage = "http://github.com/jcupitt/ruby-vips"
22
+ gem.license = "MIT"
23
+ gem.summary = %Q{Ruby extension for the vips image processing library.}
24
+ gem.description = %Q{ruby-vips is a ruby extension for vips. It is extremely fast and it can process huge images without requiring the entire image to be loaded into memory.}
25
+ gem.email = "jcupitt@gmail.com"
26
+ gem.authors = ["John Cupitt"]
27
+ # dependencies defined in Gemfile
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ task :default => :spec
38
+
39
+ require "github/markup"
40
+ require "redcarpet"
41
+ require "yard"
42
+ require "yard/rake/yardoc_task"
43
+
44
+ YARD::Rake::YardocTask.new do |yard|
45
+ end
data/TODO CHANGED
@@ -1,38 +1,14 @@
1
- - add something to make a memory image, useful in some cases, eg. making very
2
- large image mosaics
1
+ - need something like ruby-vips occasional GC stuff, we can fill memory before
2
+ a GC is triggered
3
3
 
4
- - support vips_resize()
4
+ - mail about the getpoint unimplemented error
5
5
 
6
- - support vips_flatten(), see
6
+ http://sourceforge.net/p/ruby-gnome2/mailman/ruby-gnome2-devel-en/thread/CAGNS0RuZ5N6bha3M7B0%2BYf2M9-oni44idzZO17mtQiykS%2BmJKQ%40mail.gmail.com/#msg34790843
7
7
 
8
- https://github.com/jcupitt/ruby-vips/issues/45
8
+ - still missing a few enum docs
9
9
 
10
+ - add complex constants, eg.
10
11
 
11
- btw, there's a method called to_memory in JPEGWriter and PNGWriter, that works
12
- cool to retrieve the VIPS::Image as a memory buffer, will be cool if this
13
- method is moved up to Writer and then it handles the correct to_memory method
14
- using the image headers.
12
+ Complex(1, 2)
13
+ => (1+2i)
15
14
 
16
- add from_memory? or should the open method accept a blob in place of a path?
17
-
18
-
19
-
20
-
21
- TODO
22
- * Verify that all memory gets released when vips ops return errors. Namely,
23
- make sure that the allocated IMAGEs get released via ruby's free callbacks.
24
- * Allow for injecting ruby code into an image transformation pipeline (may be
25
- slow to call out to ruby with every read, but may be worthwhile for fun custom
26
- image processors).
27
- * Tap into VIPS callback system to allow progress updates, etc.
28
- * Allow for creating a ruby endpoint to the pipeline could be useful for
29
- streaming.
30
- * Image#to_a
31
- * look into other.h, audit all libvips methods and make sure they are all
32
- implemented
33
- * JRuby support
34
- * Optional extensions to core Ruby classes, allowing operations such as
35
- [1, 2, 3] & im . This could be optionally enabled by requiring e.g.
36
- vips/core_ext
37
- * Put groups of image operations into modules, breaking docs into themes and
38
- possibly allowing for selective loading of image ops.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ im = Vips::Image.new_from_file ARGV[0], :access => :sequential
6
+
7
+ left_text = Vips::Image.text "left corner", :dpi => 300
8
+ left = left_text.embed 50, 50, im.width, 150
9
+
10
+ right_text = Vips::Image.text "right corner", :dpi => 300
11
+ right = right_text.embed im.width - right_text.width - 50, 50, im.width, 150
12
+
13
+ footer = (left | right).ifthenelse(0, [255, 0, 0], :blend => true)
14
+
15
+ im = im.insert footer, 0, im.height, :expand => true
16
+
17
+ im.write_to_file ARGV[1]
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # daltonize an image with ruby-vips
4
+ # based on
5
+ # http://scien.stanford.edu/pages/labsite/2005/psych221/projects/05/ofidaner/colorblindness_project.htm
6
+ # see
7
+ # http://libvips.blogspot.co.uk/2013/05/daltonize-in-ruby-vips-carrierwave-and.html
8
+ # for a discussion of this code
9
+
10
+ require 'vips'
11
+
12
+ #Vips.set_debug true
13
+
14
+ # matrices to convert D65 XYZ to and from bradford cone space
15
+ xyz_to_brad = [
16
+ [0.8951, 0.2664, -0.1614],
17
+ [-0.7502, 1.7135, 0.0367],
18
+ [0.0389, -0.0685, 1.0296]
19
+ ]
20
+ brad_to_xyz = [
21
+ [0.987, -0.147, 0.16],
22
+ [0.432, 0.5184, 0.0493],
23
+ [-0.0085, 0.04, 0.968]
24
+ ]
25
+
26
+ im = Vips::Image.new_from_file ARGV[0]
27
+
28
+ # remove any alpha channel before processing
29
+ alpha = nil
30
+ if im.bands == 4
31
+ alpha = im[3]
32
+ im = im.extract_band 0, :n => 3
33
+ end
34
+
35
+ begin
36
+ # import to XYZ with lcms
37
+ # if there's no profile there, we'll fall back to the thing below
38
+ xyz = im.icc_import :embedded => true, :pcs => :xyz
39
+ rescue Vips::Error
40
+ # nope .. use the built-in converter instead
41
+ xyz = im.colourspace :xyz
42
+ end
43
+
44
+ brad = xyz.recomb xyz_to_brad
45
+
46
+ # through the Deuteranope matrix
47
+ # we need rows to sum to 1 in Bradford space --- the matrix in the original
48
+ # Python code sums to 1.742
49
+ deut = brad.recomb [
50
+ [1, 0, 0],
51
+ [0.7, 0, 0.3],
52
+ [0, 0, 1]
53
+ ]
54
+
55
+ xyz = deut.recomb brad_to_xyz
56
+
57
+ # .. and back to sRGB
58
+ rgb = xyz.colourspace :srgb
59
+
60
+ # so this is the colour error
61
+ err = im - rgb
62
+
63
+ # add the error back to other channels to make a compensated image
64
+ im = im + err.recomb([
65
+ [0, 0, 0],
66
+ [0.7, 1, 0],
67
+ [0.7, 0, 1]
68
+ ])
69
+
70
+ # reattach any alpha we saved above
71
+ if alpha
72
+ im = im.bandjoin(alpha)
73
+ end
74
+
75
+ im.write_to_file ARGV[1]
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+ $vips_debug = true
5
+
6
+ puts ""
7
+ puts "starting up:"
8
+
9
+ # this makes vips keep a list of all active objects which we can print out
10
+ Vips::leak_set true
11
+
12
+ # disable the operation cache
13
+ Vips::cache_set_max 0
14
+
15
+ puts ""
16
+ puts "creating object:"
17
+ x = Vips::Image.new
18
+ Vips::Object::print_all
19
+
20
+ puts ""
21
+ puts "freeing object:"
22
+ x = nil
23
+ GC.start
24
+ Vips::Object::print_all
25
+
26
+ puts ""
27
+ puts "creating operation:"
28
+ op = Vips::Operation.new "black"
29
+ Vips::Object::print_all
30
+ op.set_property "width", 200
31
+ op.set_property "height", 300
32
+
33
+ puts ""
34
+ puts "after operation init:"
35
+ GC.start
36
+ Vips::Object::print_all
37
+
38
+ puts ""
39
+ puts "operation lookup:"
40
+ op2 = Vips::cache_operation_lookup op
41
+ if op2
42
+ puts "cache hit"
43
+ op = op2
44
+ op2 = nil
45
+ else
46
+ puts "cache miss ... building"
47
+ if not op.build
48
+ puts "*** build error"
49
+ end
50
+ Vips::cache_operation_add op
51
+ end
52
+
53
+ puts ""
54
+ puts "after build:"
55
+ GC.start
56
+ Vips::Object::print_all
57
+
58
+ puts ""
59
+ puts "fetching output:"
60
+ im = op.get_property "out"
61
+ GC.start
62
+ Vips::Object::print_all
63
+
64
+ puts ""
65
+ puts "fetching output again:"
66
+ im2 = op.get_property "out"
67
+ GC.start
68
+ Vips::Object::print_all
69
+
70
+ puts ""
71
+ puts "freeing operation:"
72
+ op.unref_outputs
73
+ op = nil
74
+ op2 = nil
75
+ GC.start
76
+ Vips::Object::print_all
77
+
78
+ puts ""
79
+ puts "shutting down:"
80
+ im = nil
81
+ im2 = nil
82
+ GC.start
83
+ Vips::shutdown
84
+ GC.start
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ puts ""
6
+ puts "starting up:"
7
+
8
+ # this makes vips keep a list of all active objects which we can print out
9
+ Vips::leak_set true
10
+
11
+ # disable the operation cache
12
+ Vips::cache_set_max 0
13
+
14
+ n = 100
15
+
16
+ n.times do |i|
17
+ puts ""
18
+ puts "call #{i} ..."
19
+ out = Vips::call "black", 200, 300
20
+ if out.width != 200 or out.height != 300
21
+ puts "bad image result from black"
22
+ end
23
+ end
24
+
25
+ puts ""
26
+ puts "after #{n} calls:"
27
+ GC.start
28
+ Vips::Object::print_all
29
+
30
+ puts ""
31
+ puts "shutting down:"
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ # this makes vips keep a list of all active objects
6
+ # Vips::leak_set true
7
+
8
+ # disable the operation cache
9
+ # Vips::cache_set_max 0
10
+
11
+ # turn on debug logging
12
+ #Vips.set_debug true
13
+
14
+ 10000.times do |i|
15
+ puts "loop #{i} ..."
16
+ im = Vips::Image.new_from_file ARGV[0]
17
+ im = im.embed 100, 100, 3000, 3000, :extend => :mirror
18
+ im.write_to_file "x.v"
19
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ # this makes vips keep a list of all active objects
6
+ Vips::leak_set true
7
+
8
+ # disable the operation cache
9
+ #Vips::cache_set_max 0
10
+
11
+ # turn on debug logging
12
+ #Vips.set_debug true
13
+
14
+ ARGV.each do |filename|
15
+ im = Vips::Image.new_from_file filename
16
+ profile = im.get_value "icc-profile-data"
17
+ puts "profile has #{profile.length} bytes"
18
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ # this makes vips keep a list of all active objects
6
+ # Vips::leak_set true
7
+
8
+ # disable the operation cache
9
+ # Vips::cache_set_max 0
10
+
11
+ # turn on debug logging
12
+ #Vips.set_debug true
13
+
14
+ if ARGV.length < 2
15
+ raise "usage: #{$PROGRAM_NAME}: input-file output-file"
16
+ end
17
+
18
+ im = Vips::Image.new_from_file ARGV[0], :access => :sequential
19
+
20
+ im *= [1, 2, 1]
21
+
22
+ # we want to be able to specify a scale for the convolution mask, so we have to
23
+ # make it ourselves
24
+ # if you are OK with scale=1, you can just pass the array directly to .conv()
25
+ mask = Vips::Image.new_from_array [
26
+ [-1, -1, -1],
27
+ [-1, 16, -1],
28
+ [-1, -1, -1]], 8
29
+ im = im.conv mask
30
+
31
+ im.write_to_file ARGV[1]
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # An equivalent of ImageMagick's -trim in ruby-vips ... automatically remove
4
+ # "boring" image edges.
5
+
6
+ # We use .project to sum the rows and columns of a 0/255 mask image, the first
7
+ # non-zero row or column is the object edge. We make the mask image with an
8
+ # amount-different-from-background image plus a threshold.
9
+
10
+ require 'vips'
11
+
12
+ im = Vips::Image.new_from_file ARGV[0]
13
+
14
+ # find the value of the pixel at (0, 0) ... we will search for all pixels
15
+ # significantly different from this
16
+ background = im.getpoint(0, 0)
17
+
18
+ # we need to smooth the image, subtract the background from every pixel, take
19
+ # the absolute value of the difference, then threshold
20
+ mask = (im.median - background).abs > 10
21
+
22
+ # sum mask rows and columns, then search for the first non-zero sum in each
23
+ # direction
24
+ columns, rows = mask.project
25
+
26
+ first_column, first_row = columns.profile
27
+ left = first_row.min
28
+
29
+ first_column, first_row = columns.fliphor.profile
30
+ right = columns.width - first_row.min
31
+
32
+ first_column, first_row = rows.profile
33
+ top = first_column.min
34
+
35
+ first_column, first_row = rows.flipver.profile
36
+ bottom = rows.height - first_column.min
37
+
38
+ # and now crop the original image
39
+ im = im.crop left, top, right - left, bottom - top
40
+
41
+ im.write_to_file ARGV[1]
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'vips'
4
+
5
+ im = Vips::Image.new_from_file ARGV[0], :access => :sequential
6
+
7
+ text = Vips::Image.text ARGV[2], :width => 500, :dpi => 300
8
+ text = (text * 0.3).cast(:uchar)
9
+ text = text.embed 100, 100, text.width + 200, text.width + 200
10
+ text = text.replicate 1 + im.width / text.width, 1 + im.height / text.height
11
+ text = text.crop 0, 0, im.width, im.height
12
+
13
+ # we want to blend into the visible part of the image and leave any alpha
14
+ # channels untouched ... we need to split im into two parts
15
+
16
+ # guess how many bands from the start of im contain visible colour information
17
+ if im.bands >= 4 and im.interpretation == :cmyk
18
+ # cmyk image
19
+ n_visible_bands = 4
20
+ text_colour = [0, 255, 0, 0]
21
+ elsif im.bands >= 3
22
+ # rgb image
23
+ n_visible_bands = 3
24
+ text_colour = [255, 0, 0]
25
+ else
26
+ # mono image
27
+ n_visible_bands = 1
28
+ text_colour = 255
29
+ end
30
+
31
+ # split into image and alpha
32
+ if im.bands - n_visible_bands > 0
33
+ alpha = im.extract_band n_visible_bands, :n => im.bands - n_visible_bands
34
+ im = im.extract_band 0, :n => n_visible_bands
35
+ else
36
+ alpha = nil
37
+ end
38
+
39
+ marked = text.ifthenelse text_colour, im, :blend => true
40
+
41
+ # reattach alpha
42
+ marked = marked.bandjoin alpha if alpha
43
+
44
+ marked.write_to_file ARGV[1]