dragonfly_libvips 2.4.2 → 2.5.1
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/workflows/test.yml +25 -0
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +12 -0
- data/Gemfile +3 -1
- data/Guardfile +3 -1
- data/Rakefile +4 -2
- data/dragonfly_libvips.gemspec +23 -19
- data/lefthook.yml +5 -0
- data/lib/dragonfly_libvips/analysers/image_properties.rb +13 -11
- data/lib/dragonfly_libvips/dimensions.rb +44 -43
- data/lib/dragonfly_libvips/plugin.rb +10 -10
- data/lib/dragonfly_libvips/processors/encode.rb +17 -17
- data/lib/dragonfly_libvips/processors/extract_area.rb +18 -16
- data/lib/dragonfly_libvips/processors/rotate.rb +18 -16
- data/lib/dragonfly_libvips/processors/thumb.rb +38 -36
- data/lib/dragonfly_libvips/version.rb +3 -1
- data/lib/dragonfly_libvips.rb +33 -15
- metadata +37 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff758f1df0a5d5e76957e22e4408a990e16e2e80627b4c1cc29fbe5fd8e2a6ac
|
4
|
+
data.tar.gz: ccb9ffe5f11e224e4672994f84dd48e3dd5157205ccac4acc543b23c51c71230
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c23ab254f3191a1c65db60aeab578aa3be6365d7cd24ce98a1ed80f08d3eed6557d4b9126cf9ff0b76e82e499d605c54dbf0c2ba4b79ac11fe7dfe67607f885
|
7
|
+
data.tar.gz: 3c97170ab5e17b824843e2936f9ddd2298b4a8fc1a8f1d48f8ddff166cbf6a7f092f71e16e932fb58f2b600661a701898094d1c13194c5c6fd2d112cb103fe5c
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Test
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
strategy:
|
7
|
+
matrix:
|
8
|
+
ruby: ['2.7', '3.2']
|
9
|
+
steps:
|
10
|
+
- uses: actions/checkout@v2
|
11
|
+
- name: Install dependencies
|
12
|
+
run: |
|
13
|
+
sudo apt-get clean
|
14
|
+
sudo apt-get update
|
15
|
+
sudo apt-get install -y gobject-introspection libgirepository1.0-dev libglib2.0-dev libpoppler-glib-dev libgif-dev
|
16
|
+
curl -OL https://github.com/libvips/libvips/releases/download/v8.13.3/vips-8.13.3.tar.gz
|
17
|
+
tar zxvf vips-8.13.3.tar.gz && cd vips-8.13.3 && ./configure $1 && sudo make && sudo make install
|
18
|
+
export GI_TYPELIB_PATH=/usr/local/lib/girepository-1.0/
|
19
|
+
sudo ldconfig
|
20
|
+
- uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby }}
|
23
|
+
bundler-cache: true
|
24
|
+
- name: Run tests
|
25
|
+
run: bundle exec rake
|
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.1.2
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 2.5.1
|
4
|
+
|
5
|
+
* Update all DragonflyLibvips.symbolize_keys to new syntax by @Bartuz
|
6
|
+
* Remove `raw` from supported output formats by @asgerb
|
7
|
+
* Add `j2c`, `j2k`, `jp2`, `jpc`, `jpt`, `jxl`, and `szi` to formats without profile support by @asgerb
|
8
|
+
* Don't pass `format` output option to `gif` by @asgerb
|
9
|
+
* Fix missing parameters in `Dimensions` by @asgerb
|
10
|
+
|
11
|
+
## 2.5.0
|
12
|
+
|
13
|
+
* Fix ruby 3.0+ compatibility by @Bartuz
|
14
|
+
|
3
15
|
## 2.4.2
|
4
16
|
|
5
17
|
* Add `webp` as supported format, and `aviz` and `heif` to formats without profile support (#14) by @asgerb
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# A sample Guardfile
|
2
4
|
# More info at https://github.com/guard/guard#readme
|
3
5
|
|
4
6
|
guard :minitest do
|
5
7
|
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
6
8
|
watch(%r{^test/.+_test\.rb$})
|
7
|
-
watch(%r{^test/test_helper\.rb$}) {
|
9
|
+
watch(%r{^test/test_helper\.rb$}) { "test" }
|
8
10
|
end
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rake/testtask"
|
3
5
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
5
7
|
t.libs << "test"
|
6
8
|
t.libs << "lib"
|
7
|
-
t.test_files = FileList[
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
12
|
+
task default: :test
|
data/dragonfly_libvips.gemspec
CHANGED
@@ -1,31 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
5
|
+
require "dragonfly_libvips/version"
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = "dragonfly_libvips"
|
8
9
|
spec.version = DragonflyLibvips::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ["Tomas Celizna"]
|
11
|
+
spec.email = ["tomas.celizna@gmail.com"]
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.summary = "Dragonfly analysers and processors for libvips image processing library."
|
14
|
+
spec.homepage = "https://github.com/tomasc/dragonfly_libvips"
|
15
|
+
spec.license = "MIT"
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir =
|
18
|
+
spec.bindir = "exe"
|
18
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ["lib"]
|
20
21
|
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
22
|
+
spec.add_dependency "dragonfly", "~> 1.0"
|
23
|
+
spec.add_dependency "ruby-vips", "~> 2.0", ">= 2.0.16"
|
23
24
|
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency "bundler" # , '~> 2.0'
|
26
|
+
spec.add_development_dependency "rb-readline"
|
27
|
+
spec.add_development_dependency "guard"
|
28
|
+
spec.add_development_dependency "guard-minitest"
|
29
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
30
|
+
spec.add_development_dependency "minitest-reporters"
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
|
33
|
+
spec.add_development_dependency "lefthook"
|
34
|
+
spec.add_development_dependency "rubocop-rails_config"
|
31
35
|
end
|
data/lefthook.yml
ADDED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "vips"
|
2
4
|
|
3
5
|
module DragonflyLibvips
|
4
6
|
module Analysers
|
@@ -10,11 +12,11 @@ module DragonflyLibvips
|
|
10
12
|
return {} unless SUPPORTED_FORMATS.include?(content.ext.downcase)
|
11
13
|
|
12
14
|
input_options = {}
|
13
|
-
input_options[
|
14
|
-
input_options[
|
15
|
-
input_options[
|
15
|
+
input_options["access"] = "sequential"
|
16
|
+
input_options["autorotate"] = true if content.mime_type == "image/jpeg"
|
17
|
+
input_options["dpi"] = DPI if content.mime_type == "application/pdf"
|
16
18
|
|
17
|
-
img = ::Vips::Image.new_from_file(content.path, DragonflyLibvips.symbolize_keys(input_options))
|
19
|
+
img = ::Vips::Image.new_from_file(content.path, **DragonflyLibvips.symbolize_keys(input_options))
|
18
20
|
|
19
21
|
width = img.width
|
20
22
|
height = img.height
|
@@ -22,12 +24,12 @@ module DragonflyLibvips
|
|
22
24
|
yres = img.yres
|
23
25
|
|
24
26
|
{
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
"format" => content.ext.to_s,
|
28
|
+
"width" => width,
|
29
|
+
"height" => height,
|
30
|
+
"xres" => xres,
|
31
|
+
"yres" => yres,
|
32
|
+
"progressive" => (content.mime_type == "image/jpeg" && img.get("jpeg-multiscan") != 0)
|
31
33
|
}
|
32
34
|
end
|
33
35
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DragonflyLibvips
|
2
4
|
class Dimensions < Struct.new(:geometry, :orig_w, :orig_h)
|
3
5
|
def self.call(*args)
|
@@ -10,60 +12,59 @@ module DragonflyLibvips
|
|
10
12
|
end
|
11
13
|
|
12
14
|
private
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def width
|
16
|
+
if landscape?
|
17
|
+
dimensions_specified_by_width? ? dimensions.width : dimensions.height / aspect_ratio
|
18
|
+
else
|
19
|
+
dimensions_specified_by_height? ? dimensions.height / aspect_ratio : dimensions.width
|
20
|
+
end
|
19
21
|
end
|
20
|
-
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def height
|
24
|
+
if landscape?
|
25
|
+
dimensions_specified_by_width? ? dimensions.width * aspect_ratio : dimensions.height
|
26
|
+
else
|
27
|
+
dimensions_specified_by_height? ? dimensions.height : dimensions.width * aspect_ratio
|
28
|
+
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def scale
|
32
|
+
width.to_f / orig_w.to_f
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def dimensions
|
36
|
+
w, h = geometry.scan(/\A(\d*)x(\d*)/).flatten.map(&:to_f)
|
37
|
+
OpenStruct.new(width: w, height: h)
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def aspect_ratio
|
41
|
+
orig_h.to_f / orig_w
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
def dimensions_specified_by_width?
|
45
|
+
dimensions.width > 0
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def dimensions_specified_by_height?
|
49
|
+
dimensions.height > 0
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
def landscape?
|
53
|
+
aspect_ratio <= 1.0
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
def portrait?
|
57
|
+
!landscape?
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
def do_not_resize_if_image_smaller_than_requested?
|
61
|
+
return false unless geometry.include? ">"
|
62
|
+
orig_w < width && orig_h < height
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
def do_not_resize_if_image_larger_than_requested?
|
66
|
+
return false unless geometry.include? "<"
|
67
|
+
orig_w > width && orig_h > height
|
68
|
+
end
|
68
69
|
end
|
69
70
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dragonfly_libvips/analysers/image_properties"
|
4
|
+
require "dragonfly_libvips/processors/encode"
|
5
|
+
require "dragonfly_libvips/processors/extract_area"
|
6
|
+
require "dragonfly_libvips/processors/rotate"
|
7
|
+
require "dragonfly_libvips/processors/thumb"
|
6
8
|
|
7
9
|
module DragonflyLibvips
|
8
10
|
class Plugin
|
@@ -24,11 +26,9 @@ module DragonflyLibvips
|
|
24
26
|
app.add_analyser(:landscape) { |c| !c.analyse(:portrait) }
|
25
27
|
|
26
28
|
app.add_analyser(:image) do |c|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
false
|
31
|
-
end
|
29
|
+
c.analyse(:image_properties).key?("format")
|
30
|
+
rescue ::Vips::Error
|
31
|
+
false
|
32
32
|
end
|
33
33
|
|
34
34
|
# Aliases
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
5
|
module DragonflyLibvips
|
6
6
|
module Processors
|
@@ -10,40 +10,40 @@ module DragonflyLibvips
|
|
10
10
|
raise UnsupportedFormat unless SUPPORTED_FORMATS.include?(content.ext.downcase)
|
11
11
|
|
12
12
|
format = format.to_s
|
13
|
-
format =
|
14
|
-
format =
|
13
|
+
format = "tif" if format == "tiff"
|
14
|
+
format = "jpg" if format == "jpeg"
|
15
15
|
|
16
16
|
raise UnsupportedOutputFormat unless SUPPORTED_OUTPUT_FORMATS.include?(format.downcase)
|
17
17
|
|
18
18
|
if content.mime_type == Rack::Mime.mime_type(".#{format}")
|
19
19
|
content.ext ||= format
|
20
|
-
content.meta[
|
20
|
+
content.meta["format"] = format
|
21
21
|
return
|
22
22
|
end
|
23
23
|
|
24
24
|
options = DragonflyLibvips.stringify_keys(options)
|
25
25
|
|
26
|
-
input_options = options.fetch(
|
27
|
-
input_options[
|
28
|
-
if content.mime_type ==
|
29
|
-
input_options[
|
26
|
+
input_options = options.fetch("input_options", {})
|
27
|
+
input_options["access"] ||= "sequential"
|
28
|
+
if content.mime_type == "image/jpeg"
|
29
|
+
input_options["autorotate"] = true unless input_options.key?("autorotate")
|
30
30
|
end
|
31
31
|
|
32
|
-
output_options = options.fetch(
|
32
|
+
output_options = options.fetch("output_options", {})
|
33
33
|
if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
|
34
|
-
output_options.delete(
|
34
|
+
output_options.delete("profile")
|
35
35
|
else
|
36
|
-
output_options[
|
36
|
+
output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
|
37
37
|
end
|
38
|
-
output_options.delete(
|
39
|
-
output_options[
|
38
|
+
output_options.delete("Q") unless /jpg|jpeg/i.match?(format.to_s)
|
39
|
+
output_options["format"] ||= format.to_s if /bmp/i.match?(format.to_s)
|
40
40
|
|
41
|
-
img = ::Vips::Image.new_from_file(content.path, DragonflyLibvips.symbolize_keys(input_options))
|
41
|
+
img = ::Vips::Image.new_from_file(content.path, **DragonflyLibvips.symbolize_keys(input_options))
|
42
42
|
|
43
43
|
content.update(
|
44
|
-
img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
|
45
|
-
|
46
|
-
|
44
|
+
img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
|
45
|
+
"name" => "temp.#{format}",
|
46
|
+
"format" => format
|
47
47
|
)
|
48
48
|
content.ext = format
|
49
49
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "vips"
|
2
4
|
|
3
5
|
module DragonflyLibvips
|
4
6
|
module Processors
|
@@ -8,38 +10,38 @@ module DragonflyLibvips
|
|
8
10
|
raise UnsupportedFormat unless SUPPORTED_FORMATS.include?(content.ext.downcase)
|
9
11
|
|
10
12
|
options = DragonflyLibvips.stringify_keys(options)
|
11
|
-
format = options.fetch(
|
13
|
+
format = options.fetch("format", content.ext)
|
12
14
|
|
13
|
-
input_options = options.fetch(
|
15
|
+
input_options = options.fetch("input_options", {})
|
14
16
|
|
15
17
|
# input_options['access'] ||= 'sequential'
|
16
|
-
if content.mime_type ==
|
17
|
-
input_options[
|
18
|
+
if content.mime_type == "image/jpeg"
|
19
|
+
input_options["autorotate"] = true unless input_options.has_key?("autorotate")
|
18
20
|
end
|
19
21
|
|
20
|
-
output_options = options.fetch(
|
22
|
+
output_options = options.fetch("output_options", {})
|
21
23
|
if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
|
22
|
-
output_options.delete(
|
24
|
+
output_options.delete("profile")
|
23
25
|
else
|
24
|
-
output_options[
|
26
|
+
output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
|
25
27
|
end
|
26
|
-
output_options.delete(
|
27
|
-
output_options[
|
28
|
+
output_options.delete("Q") unless /jpg|jpeg/i.match?(format.to_s)
|
29
|
+
output_options["format"] ||= format.to_s if /gif|bmp/i.match?(format.to_s)
|
28
30
|
|
29
|
-
img = ::Vips::Image.new_from_file(content.path, DragonflyLibvips.symbolize_keys(input_options))
|
31
|
+
img = ::Vips::Image.new_from_file(content.path, **DragonflyLibvips.symbolize_keys(input_options))
|
30
32
|
img = img.extract_area(x, y, width, height)
|
31
33
|
|
32
34
|
content.update(
|
33
|
-
img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
|
34
|
-
|
35
|
-
|
35
|
+
img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
|
36
|
+
"name" => "temp.#{format}",
|
37
|
+
"format" => format
|
36
38
|
)
|
37
39
|
content.ext = format
|
38
40
|
end
|
39
41
|
|
40
42
|
def update_url(url_attributes, _, _, _, _, options = {})
|
41
|
-
options = options.
|
42
|
-
return unless format = options.fetch(
|
43
|
+
options = options.transform_keys { |k| k.to_s } # stringify keys
|
44
|
+
return unless format = options.fetch("format", nil)
|
43
45
|
url_attributes.ext = format
|
44
46
|
end
|
45
47
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "vips"
|
2
4
|
|
3
5
|
module DragonflyLibvips
|
4
6
|
module Processors
|
@@ -8,38 +10,38 @@ module DragonflyLibvips
|
|
8
10
|
raise UnsupportedFormat unless SUPPORTED_FORMATS.include?(content.ext.downcase)
|
9
11
|
|
10
12
|
options = DragonflyLibvips.stringify_keys(options)
|
11
|
-
format = options.fetch(
|
13
|
+
format = options.fetch("format", content.ext)
|
12
14
|
|
13
|
-
input_options = options.fetch(
|
15
|
+
input_options = options.fetch("input_options", {})
|
14
16
|
|
15
17
|
# input_options['access'] ||= 'sequential'
|
16
|
-
if content.mime_type ==
|
17
|
-
input_options[
|
18
|
+
if content.mime_type == "image/jpeg"
|
19
|
+
input_options["autorotate"] = true unless input_options.has_key?("autorotate")
|
18
20
|
end
|
19
21
|
|
20
|
-
output_options = options.fetch(
|
22
|
+
output_options = options.fetch("output_options", {})
|
21
23
|
if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
|
22
|
-
output_options.delete(
|
24
|
+
output_options.delete("profile")
|
23
25
|
else
|
24
|
-
output_options[
|
26
|
+
output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
|
25
27
|
end
|
26
|
-
output_options.delete(
|
27
|
-
output_options[
|
28
|
+
output_options.delete("Q") unless /jpg|jpeg/i.match?(format.to_s)
|
29
|
+
output_options["format"] ||= format.to_s if /gif|bmp/i.match?(format.to_s)
|
28
30
|
|
29
|
-
img = ::Vips::Image.new_from_file(content.path, DragonflyLibvips.symbolize_keys(input_options))
|
31
|
+
img = ::Vips::Image.new_from_file(content.path, **DragonflyLibvips.symbolize_keys(input_options))
|
30
32
|
img = img.rot("d#{rotate}")
|
31
33
|
|
32
34
|
content.update(
|
33
|
-
img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
|
34
|
-
|
35
|
-
|
35
|
+
img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
|
36
|
+
"name" => "temp.#{format}",
|
37
|
+
"format" => format
|
36
38
|
)
|
37
39
|
content.ext = format
|
38
40
|
end
|
39
41
|
|
40
42
|
def update_url(url_attributes, _, options = {})
|
41
|
-
options = options.
|
42
|
-
return unless format = options.fetch(
|
43
|
+
options = options.transform_keys { |k| k.to_s } # stringify keys
|
44
|
+
return unless format = options.fetch("format", nil)
|
43
45
|
url_attributes.ext = format
|
44
46
|
end
|
45
47
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dragonfly_libvips/dimensions"
|
4
|
+
require "vips"
|
3
5
|
|
4
6
|
module DragonflyLibvips
|
5
7
|
module Processors
|
6
8
|
class Thumb
|
7
|
-
OPERATORS =
|
9
|
+
OPERATORS = "><"
|
8
10
|
RESIZE_GEOMETRY = /\A\d*x\d*[#{OPERATORS}]?\z/ # e.g. '300x200>'
|
9
11
|
DPI = 300
|
10
12
|
|
@@ -15,67 +17,67 @@ module DragonflyLibvips
|
|
15
17
|
options = DragonflyLibvips.stringify_keys(options)
|
16
18
|
|
17
19
|
filename = content.path
|
18
|
-
format = options.fetch(
|
20
|
+
format = options.fetch("format", content.ext).to_s
|
19
21
|
|
20
|
-
input_options = options.fetch(
|
21
|
-
input_options[
|
22
|
-
input_options[
|
22
|
+
input_options = options.fetch("input_options", {})
|
23
|
+
input_options["access"] = input_options.fetch("access", "sequential")
|
24
|
+
input_options["autorotate"] = input_options.fetch("autorotate", true) if content.mime_type == "image/jpeg"
|
23
25
|
|
24
|
-
if content.mime_type ==
|
25
|
-
input_options[
|
26
|
-
input_options[
|
26
|
+
if content.mime_type == "application/pdf"
|
27
|
+
input_options["dpi"] = input_options.fetch("dpi", DPI)
|
28
|
+
input_options["page"] = input_options.fetch("page", 0)
|
27
29
|
else
|
28
|
-
input_options.delete(
|
29
|
-
input_options.delete(
|
30
|
+
input_options.delete("page")
|
31
|
+
input_options.delete("dpi")
|
30
32
|
end
|
31
33
|
|
32
|
-
output_options = options.fetch(
|
34
|
+
output_options = options.fetch("output_options", {})
|
33
35
|
if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
|
34
|
-
output_options.delete(
|
36
|
+
output_options.delete("profile")
|
35
37
|
else
|
36
|
-
output_options[
|
38
|
+
output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
|
37
39
|
end
|
38
|
-
output_options.delete(
|
39
|
-
output_options[
|
40
|
+
output_options.delete("Q") unless /jpg|jpeg/i.match?(format.to_s)
|
41
|
+
output_options["format"] ||= format.to_s if /bmp/i.match?(format.to_s)
|
40
42
|
|
41
|
-
input_options = input_options.
|
42
|
-
img = ::Vips::Image.new_from_file(filename, DragonflyLibvips.symbolize_keys(input_options))
|
43
|
+
input_options = input_options.transform_keys { |k| k.to_sym } # symbolize
|
44
|
+
img = ::Vips::Image.new_from_file(filename, **DragonflyLibvips.symbolize_keys(input_options))
|
43
45
|
|
44
46
|
dimensions = case geometry
|
45
47
|
when RESIZE_GEOMETRY then Dimensions.call(geometry, img.width, img.height)
|
46
48
|
else raise ArgumentError, "Didn't recognise the geometry string: #{geometry}"
|
47
49
|
end
|
48
50
|
|
49
|
-
thumbnail_options = options.fetch(
|
51
|
+
thumbnail_options = options.fetch("thumbnail_options", {})
|
50
52
|
if Vips.at_least_libvips?(8, 8)
|
51
|
-
thumbnail_options[
|
53
|
+
thumbnail_options["no_rotate"] = input_options.fetch("no_rotate", false) if content.mime_type == "image/jpeg"
|
52
54
|
else
|
53
|
-
thumbnail_options[
|
55
|
+
thumbnail_options["auto_rotate"] = input_options.fetch("autorotate", true) if content.mime_type == "image/jpeg"
|
54
56
|
end
|
55
|
-
thumbnail_options[
|
56
|
-
thumbnail_options[
|
57
|
-
thumbnail_options[
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
thumbnail_options["height"] = thumbnail_options.fetch("height", dimensions.height.ceil)
|
58
|
+
thumbnail_options["import_profile"] = CMYK_PROFILE_PATH if img.get("interpretation") == :cmyk
|
59
|
+
thumbnail_options["size"] ||= case geometry
|
60
|
+
when />\z/ then :down # do_not_resize_if_image_smaller_than_requested
|
61
|
+
when /<\z/ then :up # do_not_resize_if_image_larger_than_requested
|
62
|
+
else :both
|
61
63
|
end
|
62
64
|
|
63
|
-
filename += "[page=#{input_options[:page]}]" if content.mime_type ==
|
65
|
+
filename += "[page=#{input_options[:page]}]" if content.mime_type == "application/pdf"
|
64
66
|
|
65
|
-
thumbnail_options = thumbnail_options.
|
66
|
-
thumb = ::Vips::Image.thumbnail(filename, dimensions.width.ceil, DragonflyLibvips.symbolize_keys(thumbnail_options))
|
67
|
+
thumbnail_options = thumbnail_options.transform_keys { |k| k.to_sym } # symbolize
|
68
|
+
thumb = ::Vips::Image.thumbnail(filename, dimensions.width.ceil, **DragonflyLibvips.symbolize_keys(thumbnail_options))
|
67
69
|
|
68
70
|
content.update(
|
69
|
-
thumb.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
|
70
|
-
|
71
|
-
|
71
|
+
thumb.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
|
72
|
+
"name" => "temp.#{format}",
|
73
|
+
"format" => format
|
72
74
|
)
|
73
75
|
content.ext = format
|
74
76
|
end
|
75
77
|
|
76
78
|
def update_url(url_attributes, _, options = {})
|
77
|
-
options = options.
|
78
|
-
return unless format = options.fetch(
|
79
|
+
options = options.transform_keys { |k| k.to_s } # stringify keys
|
80
|
+
return unless format = options.fetch("format", nil)
|
79
81
|
url_attributes.ext = format
|
80
82
|
end
|
81
83
|
end
|
data/lib/dragonfly_libvips.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dragonfly"
|
4
|
+
require "dragonfly_libvips/dimensions"
|
5
|
+
require "dragonfly_libvips/plugin"
|
6
|
+
require "dragonfly_libvips/version"
|
7
|
+
require "vips"
|
6
8
|
|
7
9
|
module DragonflyLibvips
|
8
10
|
class UnsupportedFormat < RuntimeError; end
|
9
11
|
class UnsupportedOutputFormat < RuntimeError; end
|
10
12
|
|
11
|
-
CMYK_PROFILE_PATH = File.expand_path(
|
12
|
-
EPROFILE_PATH = File.expand_path(
|
13
|
+
CMYK_PROFILE_PATH = File.expand_path("../vendor/cmyk.icm", __dir__)
|
14
|
+
EPROFILE_PATH = File.expand_path("../vendor/sRGB_v4_ICC_preference.icc", __dir__)
|
13
15
|
|
14
16
|
SUPPORTED_FORMATS = begin
|
15
17
|
output = `vips -l | grep -i ForeignLoad`
|
@@ -29,19 +31,35 @@ module DragonflyLibvips
|
|
29
31
|
pfm
|
30
32
|
pgm
|
31
33
|
ppm
|
34
|
+
raw
|
32
35
|
v
|
33
36
|
vips
|
34
37
|
]
|
35
38
|
|
36
|
-
FORMATS_WITHOUT_PROFILE_SUPPORT = %w[
|
39
|
+
FORMATS_WITHOUT_PROFILE_SUPPORT = %w[
|
40
|
+
avif
|
41
|
+
bmp
|
42
|
+
dz
|
43
|
+
gif
|
44
|
+
hdr
|
45
|
+
heic
|
46
|
+
heif
|
47
|
+
j2c
|
48
|
+
j2k
|
49
|
+
jp2
|
50
|
+
jpc
|
51
|
+
jpt
|
52
|
+
jxl
|
53
|
+
szi
|
54
|
+
webp
|
55
|
+
]
|
37
56
|
|
38
57
|
private
|
58
|
+
def self.stringify_keys(hash = {})
|
59
|
+
hash.transform_keys { |k| k.to_s }
|
60
|
+
end
|
39
61
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def self.symbolize_keys(hash = {})
|
45
|
-
hash.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
46
|
-
end
|
62
|
+
def self.symbolize_keys(hash = {})
|
63
|
+
hash.transform_keys { |k| k.to_sym }
|
64
|
+
end
|
47
65
|
end
|
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: 2.
|
4
|
+
version: 2.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomas Celizna
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dragonfly
|
@@ -132,16 +132,44 @@ dependencies:
|
|
132
132
|
name: rake
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
|
-
- - "
|
135
|
+
- - ">="
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: '
|
137
|
+
version: '0'
|
138
138
|
type: :development
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
|
-
- - "
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: lefthook
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: rubocop-rails_config
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
143
164
|
- !ruby/object:Gem::Version
|
144
|
-
version: '
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
145
173
|
description:
|
146
174
|
email:
|
147
175
|
- tomas.celizna@gmail.com
|
@@ -149,7 +177,9 @@ executables: []
|
|
149
177
|
extensions: []
|
150
178
|
extra_rdoc_files: []
|
151
179
|
files:
|
180
|
+
- ".github/workflows/test.yml"
|
152
181
|
- ".gitignore"
|
182
|
+
- ".rubocop.yml"
|
153
183
|
- ".ruby-version"
|
154
184
|
- ".tool-versions"
|
155
185
|
- ".travis.yml"
|
@@ -162,6 +192,7 @@ files:
|
|
162
192
|
- bin/console
|
163
193
|
- bin/setup
|
164
194
|
- dragonfly_libvips.gemspec
|
195
|
+
- lefthook.yml
|
165
196
|
- lib/dragonfly_libvips.rb
|
166
197
|
- lib/dragonfly_libvips/analysers/image_properties.rb
|
167
198
|
- lib/dragonfly_libvips/dimensions.rb
|