dragonfly_libvips 0.1.5 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e30097336afa22dd5d34b9756c4d0d6f0b8c8cd
4
- data.tar.gz: 0deda2a95f1ac84b5824b410dbd366e9c4593fff
3
+ metadata.gz: ac436d551d9ccc732c27161a35c0f80962ca7746
4
+ data.tar.gz: 53eaccc65db78f1640ad11543e1eefb38b64139a
5
5
  SHA512:
6
- metadata.gz: ba270433cfe1379aed4440cefa2bac6f283a8050a249583065b4260227cfe2a8d7ca91ad8f67088e155e2376b64fc5a3f71553bbf6b7625f1c25b0e6518a8574
7
- data.tar.gz: 4f28259621db0d059df88687c8a86cdfb3797389fed0f0178d4c257b967273b43c36af440e8bd0f5afccccc68830ee32efb3194cca255698256705d822d1f028
6
+ metadata.gz: ee485134a812e6aba9808283c87bf55c07c31ca14d1d21abf92bc32e88055498c035b5c3e944685f4574fb586f78b3a5e4924a0c8b692f269916f4072a727c1f
7
+ data.tar.gz: bd2f3aae3d786b8840cc360f63533d7d597089871e4790759d80fe611812e64cb827b5d3ef2aa226ff10f73d3dfc065dc280c6d9b30ae6971e1672c30517ea71
data/.travis.yml CHANGED
@@ -6,11 +6,16 @@ sudo: required
6
6
  dist: trusty
7
7
  rvm:
8
8
  - 2.2.5
9
- env:
10
- - LIBVIPS_VERSION_MAJOR=8 LIBVIPS_VERSION_MINOR=3 LIBVIPS_VERSION_PATCH=3 LIBVIPS_VERSION=$LIBVIPS_VERSION_MAJOR.$LIBVIPS_VERSION_MINOR.$LIBVIPS_VERSION_PATCH
11
9
  before_install:
12
10
  - gem install bundler -v 1.12.5
13
- - curl -s https://raw.githubusercontent.com/lovell/sharp/master/preinstall.sh | sudo bash -
11
+ - sudo apt-get update
12
+ - sudo apt-get install -y gobject-introspection libgirepository1.0-dev gtk-doc-tools libglib2.0-dev libpoppler-glib-dev
13
+ - export GI_TYPELIB_PATH="$VIPS_LIBDIR/girepository-1.0"
14
+ - curl -O https://poppler.freedesktop.org/poppler-0.51.0.tar.xz
15
+ - tar xf poppler-0.51.0.tar.xz && cd poppler-0.51.0 && ./configure --prefix=/usr --sysconfdir=/etc --disable-static --enable-build-type=release --enable-cmyk --enable-xpdf-headers --with-testdatadir=$PWD/testfiles && sudo make && sudo make install
16
+ - curl -O http://www.vips.ecs.soton.ac.uk/supported/8.4/vips-8.4.5.tar.gz
17
+ - tar zvxf vips-8.4.5.tar.gz && cd vips-8.4.5 && ./configure $1 --enable-introspection && sudo make && sudo make install
18
+ - sudo ldconfig
14
19
 
15
20
  notifications:
16
21
  email:
data/CHANGELOG.md CHANGED
@@ -0,0 +1,6 @@
1
+ # CHANGELOG
2
+
3
+ ## 1.0.0
4
+
5
+ * rewritten to use `ruby-vips` instead of CLI vips utils, which should result in better performance
6
+ * processors `convert`, `vips` and `vipsthumbnail` have been removed
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Dragonfly libvips
2
2
 
3
- [![Build Status](https://travis-ci.org/tomasc/dragonfly_libvips.svg)](https://travis-ci.org/tomasc/dragonfly_libvips) [![Gem Version](https://badge.fury.io/rb/dragonfly_libvips.svg)](http://badge.fury.io/rb/dragonfly_libvips) [![Coverage Status](https://img.shields.io/coveralls/tomasc/dragonfly_libvips.svg)](https://coveralls.io/r/tomasc/dragonfly_pdf)
3
+ [![Build Status](https://travis-ci.org/tomasc/dragonfly_libvips.svg)](https://travis-ci.org/tomasc/dragonfly_libvips) [![Gem Version](https://badge.fury.io/rb/dragonfly_libvips.svg)](http://badge.fury.io/rb/dragonfly_libvips) [![Coverage Status](https://img.shields.io/coveralls/tomasc/dragonfly_libvips.svg)](https://coveralls.io/r/tomasc/dragonfly_libvips)
4
4
 
5
5
  Dragonfly analysers and processors for [libvips](https://github.com/jcupitt/libvips) image processing library
6
6
 
@@ -73,7 +73,7 @@ image.encode('jpg')
73
73
  optionally pass output arguments (specific to format)
74
74
 
75
75
  ```ruby
76
- image.encode('jpg', 'Q=50')
76
+ image.encode('jpg')
77
77
  ```
78
78
 
79
79
  #### Rotate
@@ -84,41 +84,22 @@ Rotate a number of degrees with
84
84
  image.rotate(90)
85
85
  ```
86
86
 
87
- #### Vips
87
+ #### Options
88
88
 
89
- Perform an arbitrary `vips` command
89
+ All processors support `input_options` and `output_options` for passing additional options to vips. For example:
90
90
 
91
91
  ```ruby
92
- image.vips('resize', '0.5', { 'input_args' => 'page=2', 'output_args' => 'Q=50', 'format' => 'jpg' })
93
- ```
94
-
95
- corresponds to the command-line
96
-
97
- ```
98
- vips resize <original_path>[page=2] <new_path>[Q=50] 0.5
92
+ image.encode('jpg', output_options: { Q: 50 })
93
+ pdf.encode('jpg', input_options: { page: 0, dpi: 600 })
99
94
  ```
100
95
 
101
- #### Vipsthumbnail
102
-
103
- Perform an arbitrary `vipsthumbnail` command
96
+ Defaults:
104
97
 
105
98
  ```ruby
106
- image.vipsthumbnail('--size=100x100', { 'input_args' => 'page=2', 'output_args' => 'Q=50', 'format' => 'jpg' })
99
+ input_options: { access: :sequential }
100
+ output_options: { profile: … } # embeds 'sRGB_v4_ICC_preference.icc' profile included with this gem
107
101
  ```
108
102
 
109
- corresponds to the command-line
110
-
111
- ```
112
- vipsthumbnail <original_path>[page=2] --size=100x100 -o <new-path>[Q=50] --eprofile=./vendor/sRGB_v4_ICC_preference.icc
113
- ```
114
-
115
- Please note that unless specified a default sRGB profile is added (required for conversion from CMYK, for example). It can be overridden by specifying alternative on in the processors args:
116
-
117
- ```ruby
118
- image.vipsthumbnail('--size=100x100 --eprofile=./my_custom_profile.icc')
119
- ```
120
-
121
-
122
103
  ### Analysers
123
104
 
124
105
  The following methods are provided
@@ -126,6 +107,8 @@ The following methods are provided
126
107
  ```ruby
127
108
  image.width # => 280
128
109
  image.height # => 355
110
+ image.xres # => 72.0
111
+ image.yres # => 72.0
129
112
  image.aspect_ratio # => 0.788732394366197
130
113
  image.portrait? # => true
131
114
  image.landscape? # => false
@@ -133,21 +116,6 @@ image.format # => 'png'
133
116
  image.image? # => true
134
117
  ```
135
118
 
136
- ### Configuration
137
-
138
- ```ruby
139
- Dragonfly.app.configure do
140
- plugin :libvips,
141
- vips_command: "/opt/local/bin/vips" # defaults to "vips"
142
- vipsheader_command: "/opt/local/bin/vipsheader" # defaults to "vipsheader"
143
- vipsthumbnail_command: "/opt/local/bin/vipsthumbnail" # defaults to "vipsthumbnail"
144
- end
145
- ```
146
-
147
- ## Acknowledgements
148
-
149
- This plugin, its structure, sample files, tests as well as this README are based on the original Dragonfly's [ImageMagick plugin](http://markevans.github.io/dragonfly/imagemagick) by Mark Evans.
150
-
151
119
  ## Development
152
120
 
153
121
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'dragonfly', '~> 1.0'
22
+ spec.add_dependency 'ruby-vips', '~> 1.0'
23
+ spec.add_dependency 'activesupport', '>= 4.0'
22
24
 
23
25
  spec.add_development_dependency 'bundler', '~> 1.12'
24
26
  spec.add_development_dependency 'guard'
@@ -1,20 +1,17 @@
1
+ require 'vips'
2
+
1
3
  module DragonflyLibvips
2
4
  module Analysers
3
5
  class ImageProperties
4
6
  def call(content)
5
- vipsheader_command = content.env[:vipsheader_command] || 'vipsheader'
6
- details = content.shell_eval do |path|
7
- "#{vipsheader_command} #{path}"
8
- end
9
-
10
- _filename, dimensions, _bands, _interpretation, vips_loader = details.split(/\s*[:,]\s*/)
11
- width, height = dimensions.split(/\s+/).first.split('x')
12
- format = vips_loader.gsub(/\s*load\s*/, '').downcase
7
+ img = ::Vips::Image.new_from_file(content.path, access: :sequential)
13
8
 
14
9
  {
15
- 'format' => format.downcase,
16
- 'width' => width.to_i,
17
- 'height' => height.to_i
10
+ 'format' => content.ext,
11
+ 'width' => img.width,
12
+ 'height' => img.height,
13
+ 'xres' => img.xres,
14
+ 'yres' => img.yres
18
15
  }
19
16
  end
20
17
  end
@@ -5,8 +5,8 @@ module DragonflyLibvips
5
5
  end
6
6
 
7
7
  def call
8
- return OpenStruct.new(width: orig_w, height: orig_h) if do_not_resize_if_image_smaller_than_requested? || do_not_resize_if_image_larger_than_requested?
9
- OpenStruct.new(width: width, height: height)
8
+ return OpenStruct.new(width: orig_w, height: orig_h, scale: 1) if do_not_resize_if_image_smaller_than_requested? || do_not_resize_if_image_larger_than_requested?
9
+ OpenStruct.new(width: width, height: height, scale: scale)
10
10
  end
11
11
 
12
12
  private
@@ -27,6 +27,10 @@ module DragonflyLibvips
27
27
  end
28
28
  end
29
29
 
30
+ def scale
31
+ width.to_f / orig_w.to_f
32
+ end
33
+
30
34
  def dimensions
31
35
  w, h = geometry.scan(/\A(\d*)x(\d*)/).flatten.map(&:to_f)
32
36
  OpenStruct.new(width: w, height: h)
@@ -1,18 +1,11 @@
1
- require 'dragonfly/shell'
2
1
  require 'dragonfly_libvips/analysers/image_properties'
3
2
  require 'dragonfly_libvips/processors/encode'
3
+ require 'dragonfly_libvips/processors/rotate'
4
4
  require 'dragonfly_libvips/processors/thumb'
5
- require 'dragonfly_libvips/processors/vips'
6
- require 'dragonfly_libvips/processors/vipsthumbnail'
7
5
 
8
6
  module DragonflyLibvips
9
7
  class Plugin
10
- def call(app, opts = {})
11
- # ENV
12
- app.env[:vips_command] = opts[:vips_command] || 'vips'
13
- app.env[:vipsheader_command] = opts[:vipsheader_command] || 'vipsheader'
14
- app.env[:vipsthumbnail_command] = opts[:vipsthumbnail_command] || 'vipsthumbnail'
15
-
8
+ def call(app, _opts = {})
16
9
  # Analysers
17
10
  app.add_analyser :image_properties, DragonflyLibvips::Analysers::ImageProperties.new
18
11
 
@@ -24,6 +17,14 @@ module DragonflyLibvips
24
17
  content.analyse(:image_properties)['height']
25
18
  end
26
19
 
20
+ app.add_analyser :xres do |content|
21
+ content.analyse(:image_properties)['xres']
22
+ end
23
+
24
+ app.add_analyser :yres do |content|
25
+ content.analyse(:image_properties)['yres']
26
+ end
27
+
27
28
  app.add_analyser :format do |content|
28
29
  content.analyse(:image_properties)['format']
29
30
  end
@@ -45,7 +46,7 @@ module DragonflyLibvips
45
46
  app.add_analyser :image do |content|
46
47
  begin
47
48
  content.analyse(:image_properties).key?('format')
48
- rescue Dragonfly::Shell::CommandFailed
49
+ rescue ::Vips::Error
49
50
  false
50
51
  end
51
52
  end
@@ -58,19 +59,7 @@ module DragonflyLibvips
58
59
  # Processors
59
60
  app.add_processor :encode, Processors::Encode.new
60
61
  app.add_processor :thumb, Processors::Thumb.new
61
- app.add_processor :vips, Processors::Vips.new
62
- app.add_processor :vipsthumbnail, Processors::Vipsthumbnail.new
63
- app.add_processor :rotate do |content, amount|
64
- content.process!(:vips, 'rot', "d#{amount}")
65
- end
66
-
67
- # Extra methods
68
- app.define :vipsheader do |*args|
69
- cli_args = args.first # because ruby 1.8.7 can't deal with default args in blocks
70
- shell_eval do |path|
71
- "#{app.env[:vipsheader_command]} #{cli_args} #{path}"
72
- end
73
- end
62
+ app.add_processor :rotate, Processors::Rotate.new
74
63
  end
75
64
  end
76
65
  end
@@ -1,13 +1,26 @@
1
+ require 'active_support/core_ext/hash'
2
+ require 'vips'
3
+
1
4
  module DragonflyLibvips
2
5
  module Processors
3
6
  class Encode
4
- def call(content, format, output_args = '')
5
- opts = { 'format' => format, 'output_args' => output_args }
6
- content.process!(:vips, 'copy', '', opts)
7
+ def call(content, format, options = {})
8
+ options = options.deep_stringify_keys
9
+
10
+ input_options = options.fetch('input_options', {})
11
+ output_options = options.fetch('output_options', {})
12
+
13
+ input_options['access'] ||= 'sequential'
14
+ output_options['profile'] ||= DragonflyLibvips::EPROFILE_PATH
15
+
16
+ img = ::Vips::Image.new_from_file(content.path, input_options)
17
+
18
+ content.update(img.write_to_buffer(".#{format}", output_options), 'format' => format)
19
+ content.ext = format
7
20
  end
8
21
 
9
- def update_url(attrs, format, _args = '')
10
- attrs.ext = format.to_s
22
+ def update_url(url_attributes, format, options = {})
23
+ url_attributes.ext = format.to_s
11
24
  end
12
25
  end
13
26
  end
@@ -0,0 +1,35 @@
1
+ require 'active_support/core_ext/hash'
2
+ require 'vips'
3
+
4
+ module DragonflyLibvips
5
+ module Processors
6
+ class Rotate
7
+ def call(content, rotate, options = {})
8
+ options = options.deep_stringify_keys
9
+
10
+ format = options.fetch('format', content.ext)
11
+
12
+ input_options = options.fetch('input_options', {})
13
+ output_options = options.fetch('output_options', {})
14
+
15
+ input_options['access'] ||= 'sequential'
16
+ output_options['profile'] ||= DragonflyLibvips::EPROFILE_PATH
17
+
18
+ img = ::Vips::Image.new_from_file(content.path, input_options)
19
+
20
+ img = img.rot("d#{rotate}")
21
+
22
+ content.update(img.write_to_buffer(".#{format}", output_options), 'format' => format)
23
+ content.ext = format
24
+ end
25
+
26
+ def update_url(url_attributes, _, options = {})
27
+ options = options.deep_stringify_keys
28
+
29
+ if format = options.fetch('format', nil)
30
+ url_attributes.ext = format
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,34 +1,47 @@
1
+ require 'active_support/core_ext/hash'
1
2
  require 'dragonfly_libvips/dimensions'
3
+ require 'vips'
2
4
 
3
5
  module DragonflyLibvips
4
6
  module Processors
5
7
  class Thumb
6
8
  OPERATORS = '><'.freeze
7
9
  RESIZE_GEOMETRY = /\A\d*x\d*[#{OPERATORS}]?\z/ # e.g. '300x200>'
10
+ RESIZE_KEYS = %w(kernel).freeze
8
11
 
9
- def call(content, geometry, opts = {})
10
- image_properties = content.analyse(:image_properties)
11
- args = [args_for_geometry(geometry, image_properties), opts['args']].compact.join(' ')
12
- content.process!(:vipsthumbnail, args, opts)
13
- end
12
+ def call(content, geometry, options = {})
13
+ options = options.deep_stringify_keys
14
14
 
15
- def update_url(url_attributes, _geometry, opts = {})
16
- format = opts['format']
17
- url_attributes.ext = format if format
18
- end
15
+ format = options.fetch('format', content.ext)
16
+
17
+ input_options = options.fetch('input_options', {})
18
+ resize_options = options.fetch('resize_options', {})
19
+ output_options = options.fetch('output_options', {})
19
20
 
20
- private
21
+ input_options['access'] ||= 'sequential'
22
+ output_options['profile'] ||= DragonflyLibvips::EPROFILE_PATH
21
23
 
22
- def args_for_geometry(geometry, image_properties)
23
- case geometry
24
- when RESIZE_GEOMETRY then resize_args(geometry, image_properties)
25
- else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
24
+ img = ::Vips::Image.new_from_file(content.path, input_options)
25
+
26
+ dimensions = case geometry
27
+ when RESIZE_GEOMETRY then DragonflyLibvips::Dimensions.call(geometry, img.width, img.height)
28
+ else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
26
29
  end
30
+
31
+ if dimensions.scale != 1
32
+ img = img.resize(dimensions.scale, resize_options)
33
+ end
34
+
35
+ content.update(img.write_to_buffer(".#{format}", output_options), 'format' => format)
36
+ content.ext = format
27
37
  end
28
38
 
29
- def resize_args(geometry, image_properties)
30
- res = DragonflyLibvips::Dimensions.call(geometry, image_properties['width'], image_properties['height'])
31
- "-s #{res.width.round}x#{res.height.round}"
39
+ def update_url(url_attributes, _, options = {})
40
+ options = options.deep_stringify_keys
41
+
42
+ if format = options.fetch('format', nil)
43
+ url_attributes.ext = format
44
+ end
32
45
  end
33
46
  end
34
47
  end
@@ -1,3 +1,3 @@
1
1
  module DragonflyLibvips
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '1.0.2'.freeze
3
3
  end
@@ -2,6 +2,7 @@ require 'dragonfly'
2
2
  require 'dragonfly_libvips/dimensions'
3
3
  require 'dragonfly_libvips/plugin'
4
4
  require 'dragonfly_libvips/version'
5
+ require 'vips'
5
6
 
6
7
  module DragonflyLibvips
7
8
  EPROFILE_PATH = File.expand_path('../vendor/sRGB_v4_ICC_preference.icc', __dir__)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dragonfly_libvips
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Celizna
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-22 00:00:00.000000000 Z
11
+ date: 2017-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dragonfly
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-vips
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -117,9 +145,8 @@ files:
117
145
  - lib/dragonfly_libvips/dimensions.rb
118
146
  - lib/dragonfly_libvips/plugin.rb
119
147
  - lib/dragonfly_libvips/processors/encode.rb
148
+ - lib/dragonfly_libvips/processors/rotate.rb
120
149
  - lib/dragonfly_libvips/processors/thumb.rb
121
- - lib/dragonfly_libvips/processors/vips.rb
122
- - lib/dragonfly_libvips/processors/vipsthumbnail.rb
123
150
  - lib/dragonfly_libvips/version.rb
124
151
  - samples/beach.png
125
152
  - samples/landscape_beach.png
@@ -1,32 +0,0 @@
1
- module DragonflyLibvips
2
- module Processors
3
- class Vips
4
- def call(content, commands, args = '', opts = {})
5
- vips_command = content.env[:vips_command] || 'vips'
6
- format = opts['format']
7
-
8
- if input_args = opts['input_args']
9
- input_args = "[#{input_args}]"
10
- end
11
-
12
- if output_args = opts['output_args']
13
- output_args = "[#{output_args}]"
14
- end
15
-
16
- content.shell_update ext: format do |old_path, new_path|
17
- "#{vips_command} #{commands} #{old_path}#{input_args} #{new_path}#{output_args} #{args}"
18
- end
19
-
20
- if format
21
- content.meta['format'] = format.to_s
22
- content.ext = format
23
- end
24
- end
25
-
26
- def update_url(attrs, _commands, _args = '', opts = {})
27
- format = opts['format']
28
- attrs.ext = format if format
29
- end
30
- end
31
- end
32
- end
@@ -1,36 +0,0 @@
1
- require 'dragonfly_libvips'
2
-
3
- module DragonflyLibvips
4
- module Processors
5
- class Vipsthumbnail
6
- def call(content, args = '', opts = {})
7
- vipsthumbnail_command = content.env[:vipsthumbnail_command] || 'vipsthumbnail'
8
- format = opts['format']
9
-
10
- if input_args = opts['input_args']
11
- input_args = "[#{input_args}]"
12
- end
13
-
14
- if output_args = opts['output_args']
15
- output_args = "[#{output_args}]"
16
- end
17
-
18
- args = [args, "--eprofile=#{EPROFILE_PATH}"].compact.join(' ') unless args.include?('eprofile')
19
-
20
- content.shell_update ext: format do |old_path, new_path|
21
- "#{vipsthumbnail_command} #{old_path}#{input_args} -o #{new_path}#{output_args} #{args}"
22
- end
23
-
24
- if format
25
- content.meta['format'] = format.to_s
26
- content.ext = format
27
- end
28
- end
29
-
30
- def update_url(attrs, _args = '', opts = {})
31
- format = opts['format']
32
- attrs.ext = format if format
33
- end
34
- end
35
- end
36
- end