dragonfly_libvips 2.5.0 → 2.6.0

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
  SHA256:
3
- metadata.gz: 1d406440d81b35a36ff76d957aec2605e79caf29faac9df5225d91eb0a29ae9a
4
- data.tar.gz: e33e09b0c99cdc864b082c32f0c459fd7a6c5775b0eeff9534e6ff33a0e91650
3
+ metadata.gz: 507faa296ab3057e5b71b9fd85b0c9314ba77b748c2e23983dfb5bfbb46203f2
4
+ data.tar.gz: 47eec77cb209df469e4caf83a6102a4d0af6dc3452799bb441c305c8fe5f5faf
5
5
  SHA512:
6
- metadata.gz: d43526ee56067f3d44f9f5af1a83b2be59e1e48b3dabca86d96503710b83483c8a7369d5f928978ca358c7610e890ae62501853d5f889451717ff0f390bb9702
7
- data.tar.gz: 04daf214847dc14d7686d85fbeaaa0eefea256cd429ac1a9912e16cfcc5c87d384b5b065b9f0e208ca740bfed5cd07c673f89ecb36ed3a71d7f4dda9343d3b96
6
+ metadata.gz: d13cd15073052fcbd5f7de59f5a6462662c98a083c1e348ebb4747a72fece6266261c9bac8ed2af97f693f930a2f3861c9a07d403dad49ec2cf1fa407fa6288b
7
+ data.tar.gz: ed631f529a74d9dbe21ae4810f24e9d237da89fa5495a400c81f7e2b2875f765be3370e10b541f459e5776fafac475f49614eb4d8edbf9712c4fddbb5cd76545
@@ -0,0 +1,29 @@
1
+ name: Test
2
+ on:
3
+ pull_request:
4
+ branches: ["master"]
5
+ push:
6
+ branches: ["master"]
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby: ['2.7', '3.2']
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Install dependencies
16
+ run: |
17
+ sudo apt-get clean
18
+ sudo apt-get update
19
+ sudo apt-get install -y gobject-introspection libgirepository1.0-dev libglib2.0-dev libpoppler-glib-dev libgif-dev
20
+ curl -OL https://github.com/libvips/libvips/releases/download/v8.13.3/vips-8.13.3.tar.gz
21
+ tar zxvf vips-8.13.3.tar.gz && cd vips-8.13.3 && ./configure $1 && sudo make && sudo make install
22
+ export GI_TYPELIB_PATH=/usr/local/lib/girepository-1.0/
23
+ sudo ldconfig
24
+ - uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby }}
27
+ bundler-cache: true
28
+ - name: Run tests
29
+ run: bundle exec rake
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ inherit_gem:
2
+ rubocop-rails_config:
3
+ - config/rails.yml
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 3.1
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.3
1
+ 3.4.5
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.6.3
1
+ ruby 3.4.5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 2.6.0
4
+
5
+ * Add auto_profile configuration option by @asgerb
6
+ * Fix output not having the ICC profile embedded by @asgerb
7
+
8
+ ## 2.5.1
9
+
10
+ * Update all DragonflyLibvips.symbolize_keys to new syntax by @Bartuz
11
+ * Remove `raw` from supported output formats by @asgerb
12
+ * Add `j2c`, `j2k`, `jp2`, `jpc`, `jpt`, `jxl`, and `szi` to formats without profile support by @asgerb
13
+ * Don't pass `format` output option to `gif` by @asgerb
14
+ * Fix missing parameters in `Dimensions` by @asgerb
15
+
3
16
  ## 2.5.0
4
17
 
5
18
  * Fix ruby 3.0+ compatibility by @Bartuz
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in dragonfly_libvips.gemspec
4
6
  gemspec
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$}) { 'test' }
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['test/**/*_test.rb']
9
+ t.test_files = FileList["test/**/*_test.rb"]
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
@@ -1,31 +1,35 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path('lib', __dir__)
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'dragonfly_libvips/version'
5
+ require "dragonfly_libvips/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = 'dragonfly_libvips'
8
+ spec.name = "dragonfly_libvips"
8
9
  spec.version = DragonflyLibvips::VERSION
9
- spec.authors = ['Tomas Celizna']
10
- spec.email = ['tomas.celizna@gmail.com']
10
+ spec.authors = ["Tomas Celizna"]
11
+ spec.email = ["tomas.celizna@gmail.com"]
11
12
 
12
- spec.summary = 'Dragonfly analysers and processors for libvips image processing library.'
13
- spec.homepage = 'https://github.com/tomasc/dragonfly_libvips'
14
- spec.license = 'MIT'
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 = 'exe'
18
+ spec.bindir = "exe"
18
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.require_paths = ['lib']
20
+ spec.require_paths = ["lib"]
20
21
 
21
- spec.add_dependency 'dragonfly', '~> 1.0'
22
- spec.add_dependency 'ruby-vips', '~> 2.0', '>= 2.0.16'
22
+ spec.add_dependency "dragonfly", "~> 1.0"
23
+ spec.add_dependency "ruby-vips", "~> 2.0", ">= 2.0.16"
24
+ spec.add_dependency "base64"
23
25
 
24
- spec.add_development_dependency 'bundler'#, '~> 2.0'
25
- spec.add_development_dependency 'rb-readline'
26
- spec.add_development_dependency 'guard'
27
- spec.add_development_dependency 'guard-minitest'
28
- spec.add_development_dependency 'minitest', '~> 5.0'
29
- spec.add_development_dependency 'minitest-reporters'
30
- spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency "bundler" # , '~> 2.0'
27
+ spec.add_development_dependency "rb-readline"
28
+ spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-minitest"
30
+ spec.add_development_dependency "minitest", "~> 5.0"
31
+ spec.add_development_dependency "minitest-reporters"
32
+ spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "lefthook"
34
+ spec.add_development_dependency "rubocop-rails_config"
31
35
  end
data/lefthook.yml ADDED
@@ -0,0 +1,5 @@
1
+ pre-commit:
2
+ parallel: true
3
+ commands:
4
+ rubocop:
5
+ run: bundle exec rubocop {staged_files} -A --display-cop-names --extra-details --force-exclusion
@@ -1,4 +1,6 @@
1
- require 'vips'
1
+ # frozen_string_literal: true
2
+
3
+ require "vips"
2
4
 
3
5
  module DragonflyLibvips
4
6
  module Analysers
@@ -10,9 +12,9 @@ module DragonflyLibvips
10
12
  return {} unless SUPPORTED_FORMATS.include?(content.ext.downcase)
11
13
 
12
14
  input_options = {}
13
- input_options['access'] = 'sequential'
14
- input_options['autorotate'] = true if content.mime_type == 'image/jpeg'
15
- input_options['dpi'] = DPI if content.mime_type == 'application/pdf'
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
19
  img = ::Vips::Image.new_from_file(content.path, **DragonflyLibvips.symbolize_keys(input_options))
18
20
 
@@ -22,12 +24,13 @@ module DragonflyLibvips
22
24
  yres = img.yres
23
25
 
24
26
  {
25
- 'format' => content.ext.to_s,
26
- 'width' => width,
27
- 'height' => height,
28
- 'xres' => xres,
29
- 'yres' => yres,
30
- 'progressive' => (content.mime_type == 'image/jpeg' && img.get('jpeg-multiscan') != 0)
27
+ "format" => content.ext.to_s,
28
+ "width" => width,
29
+ "height" => height,
30
+ "xres" => xres,
31
+ "yres" => yres,
32
+ "has_alpha" => img.has_alpha?,
33
+ "progressive" => (content.mime_type == "image/jpeg" && img.get("jpeg-multiscan") != 0)
31
34
  }
32
35
  end
33
36
  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
- def width
15
- if landscape?
16
- dimensions_specified_by_width? ? dimensions.width : dimensions.height / aspect_ratio
17
- else
18
- dimensions_specified_by_height? ? dimensions.height / aspect_ratio : dimensions.width
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
- def height
23
- if landscape?
24
- dimensions_specified_by_width? ? dimensions.width * aspect_ratio : dimensions.height
25
- else
26
- dimensions_specified_by_height? ? dimensions.height : dimensions.width * aspect_ratio
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
- def scale
31
- width.to_f / orig_w.to_f
32
- end
31
+ def scale
32
+ width.to_f / orig_w.to_f
33
+ end
33
34
 
34
- def dimensions
35
- w, h = geometry.scan(/\A(\d*)x(\d*)/).flatten.map(&:to_f)
36
- OpenStruct.new(width: w, height: h)
37
- end
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
- def aspect_ratio
40
- orig_h.to_f / orig_w
41
- end
40
+ def aspect_ratio
41
+ orig_h.to_f / orig_w
42
+ end
42
43
 
43
- def dimensions_specified_by_width?
44
- dimensions.width > 0
45
- end
44
+ def dimensions_specified_by_width?
45
+ dimensions.width > 0
46
+ end
46
47
 
47
- def dimensions_specified_by_height?
48
- dimensions.height > 0
49
- end
48
+ def dimensions_specified_by_height?
49
+ dimensions.height > 0
50
+ end
50
51
 
51
- def landscape?
52
- aspect_ratio <= 1.0
53
- end
52
+ def landscape?
53
+ aspect_ratio <= 1.0
54
+ end
54
55
 
55
- def portrait?
56
- !landscape?
57
- end
56
+ def portrait?
57
+ !landscape?
58
+ end
58
59
 
59
- def do_not_resize_if_image_smaller_than_requested?
60
- return false unless geometry.include? '>'
61
- orig_w < width && orig_h < height
62
- end
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
- def do_not_resize_if_image_larger_than_requested?
65
- return false unless geometry.include? '<'
66
- orig_w > width && orig_h > height
67
- end
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
- require 'dragonfly_libvips/analysers/image_properties'
2
- require 'dragonfly_libvips/processors/encode'
3
- require 'dragonfly_libvips/processors/extract_area'
4
- require 'dragonfly_libvips/processors/rotate'
5
- require 'dragonfly_libvips/processors/thumb'
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
- begin
28
- c.analyse(:image_properties).key?('format')
29
- rescue ::Vips::Error
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 'vips'
3
+ require "vips"
4
4
 
5
5
  module DragonflyLibvips
6
6
  module Processors
@@ -10,40 +10,49 @@ module DragonflyLibvips
10
10
  raise UnsupportedFormat unless SUPPORTED_FORMATS.include?(content.ext.downcase)
11
11
 
12
12
  format = format.to_s
13
- format = 'tif' if format == 'tiff'
14
- format = 'jpg' if format == 'jpeg'
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['format'] = format
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('input_options', {})
27
- input_options['access'] ||= 'sequential'
28
- if content.mime_type == 'image/jpeg'
29
- input_options['autorotate'] = true unless input_options.key?('autorotate')
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('output_options', {})
32
+ output_options = options.fetch("output_options", {})
33
33
  if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
34
- output_options.delete('profile')
35
- else
36
- output_options['profile'] ||= input_options.fetch('profile', EPROFILE_PATH)
34
+ output_options.delete("profile")
35
+ elsif DragonflyLibvips.auto_profile
36
+ output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
37
37
  end
38
- output_options.delete('Q') unless format.to_s =~ /jpg|jpeg/i
39
- output_options['format'] ||= format.to_s if format.to_s =~ /gif|bmp/i
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
+
43
+ if output_options.include?("profile")
44
+ img = img.icc_transform(
45
+ output_options["profile"],
46
+ embedded: true,
47
+ intent: :relative,
48
+ black_point_compensation: true
49
+ )
50
+ end
42
51
 
43
52
  content.update(
44
- img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
45
- 'name' => "temp.#{format}",
46
- 'format' => format
53
+ img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
54
+ "name" => "temp.#{format}",
55
+ "format" => format
47
56
  )
48
57
  content.ext = format
49
58
  end
@@ -1,4 +1,6 @@
1
- require 'vips'
1
+ # frozen_string_literal: true
2
+
3
+ require "vips"
2
4
 
3
5
  module DragonflyLibvips
4
6
  module Processors
@@ -8,38 +10,47 @@ 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('format', content.ext)
13
+ format = options.fetch("format", content.ext)
12
14
 
13
- input_options = options.fetch('input_options', {})
15
+ input_options = options.fetch("input_options", {})
14
16
 
15
17
  # input_options['access'] ||= 'sequential'
16
- if content.mime_type == 'image/jpeg'
17
- input_options['autorotate'] = true unless input_options.has_key?('autorotate')
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('output_options', {})
22
+ output_options = options.fetch("output_options", {})
21
23
  if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
22
- output_options.delete('profile')
23
- else
24
- output_options['profile'] ||= input_options.fetch('profile', EPROFILE_PATH)
24
+ output_options.delete("profile")
25
+ elsif DragonflyLibvips.auto_profile
26
+ output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
25
27
  end
26
- output_options.delete('Q') unless format.to_s =~ /jpg|jpeg/i
27
- output_options['format'] ||= format.to_s if format.to_s =~ /gif|bmp/i
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
 
34
+ if output_options.include?("profile")
35
+ img = img.icc_transform(
36
+ output_options["profile"],
37
+ embedded: true,
38
+ intent: :relative,
39
+ black_point_compensation: true
40
+ )
41
+ end
42
+
32
43
  content.update(
33
- img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
34
- 'name' => "temp.#{format}",
35
- 'format' => format
44
+ img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
45
+ "name" => "temp.#{format}",
46
+ "format" => format
36
47
  )
37
48
  content.ext = format
38
49
  end
39
50
 
40
51
  def update_url(url_attributes, _, _, _, _, options = {})
41
- options = options.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v } # stringify keys
42
- return unless format = options.fetch('format', nil)
52
+ options = options.transform_keys { |k| k.to_s } # stringify keys
53
+ return unless format = options.fetch("format", nil)
43
54
  url_attributes.ext = format
44
55
  end
45
56
  end
@@ -1,4 +1,6 @@
1
- require 'vips'
1
+ # frozen_string_literal: true
2
+
3
+ require "vips"
2
4
 
3
5
  module DragonflyLibvips
4
6
  module Processors
@@ -8,38 +10,47 @@ 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('format', content.ext)
13
+ format = options.fetch("format", content.ext)
12
14
 
13
- input_options = options.fetch('input_options', {})
15
+ input_options = options.fetch("input_options", {})
14
16
 
15
17
  # input_options['access'] ||= 'sequential'
16
- if content.mime_type == 'image/jpeg'
17
- input_options['autorotate'] = true unless input_options.has_key?('autorotate')
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('output_options', {})
22
+ output_options = options.fetch("output_options", {})
21
23
  if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
22
- output_options.delete('profile')
23
- else
24
- output_options['profile'] ||= input_options.fetch('profile', EPROFILE_PATH)
24
+ output_options.delete("profile")
25
+ elsif DragonflyLibvips.auto_profile
26
+ output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
25
27
  end
26
- output_options.delete('Q') unless format.to_s =~ /jpg|jpeg/i
27
- output_options['format'] ||= format.to_s if format.to_s =~ /gif|bmp/i
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
 
34
+ if output_options.include?("profile")
35
+ img = img.icc_transform(
36
+ output_options["profile"],
37
+ embedded: true,
38
+ intent: :relative,
39
+ black_point_compensation: true
40
+ )
41
+ end
42
+
32
43
  content.update(
33
- img.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
34
- 'name' => "temp.#{format}",
35
- 'format' => format
44
+ img.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
45
+ "name" => "temp.#{format}",
46
+ "format" => format
36
47
  )
37
48
  content.ext = format
38
49
  end
39
50
 
40
51
  def update_url(url_attributes, _, options = {})
41
- options = options.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v } # stringify keys
42
- return unless format = options.fetch('format', nil)
52
+ options = options.transform_keys { |k| k.to_s } # stringify keys
53
+ return unless format = options.fetch("format", nil)
43
54
  url_attributes.ext = format
44
55
  end
45
56
  end
@@ -1,10 +1,12 @@
1
- require 'dragonfly_libvips/dimensions'
2
- require 'vips'
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 = '><'.freeze
9
+ OPERATORS = "><"
8
10
  RESIZE_GEOMETRY = /\A\d*x\d*[#{OPERATORS}]?\z/ # e.g. '300x200>'
9
11
  DPI = 300
10
12
 
@@ -15,67 +17,76 @@ module DragonflyLibvips
15
17
  options = DragonflyLibvips.stringify_keys(options)
16
18
 
17
19
  filename = content.path
18
- format = options.fetch('format', content.ext).to_s
20
+ format = options.fetch("format", content.ext).to_s
19
21
 
20
- input_options = options.fetch('input_options', {})
21
- input_options['access'] = input_options.fetch('access', 'sequential')
22
- input_options['autorotate'] = input_options.fetch('autorotate', true) if content.mime_type == 'image/jpeg'
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 == 'application/pdf'
25
- input_options['dpi'] = input_options.fetch('dpi', DPI)
26
- input_options['page'] = input_options.fetch('page', 0)
27
- else
28
- input_options.delete('page')
29
- input_options.delete('dpi')
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)
29
+ elsif DragonflyLibvips.auto_profile
30
+ input_options.delete("page")
31
+ input_options.delete("dpi")
30
32
  end
31
33
 
32
- output_options = options.fetch('output_options', {})
34
+ output_options = options.fetch("output_options", {})
33
35
  if FORMATS_WITHOUT_PROFILE_SUPPORT.include?(format)
34
- output_options.delete('profile')
36
+ output_options.delete("profile")
35
37
  else
36
- output_options['profile'] ||= input_options.fetch('profile', EPROFILE_PATH)
38
+ output_options["profile"] ||= input_options.fetch("profile", EPROFILE_PATH)
37
39
  end
38
- output_options.delete('Q') unless format.to_s =~ /jpg|jpeg/i
39
- output_options['format'] ||= format.to_s if format.to_s =~ /gif|bmp/i
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.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v } # symbolize
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('thumbnail_options', {})
51
+ thumbnail_options = options.fetch("thumbnail_options", {})
50
52
  if Vips.at_least_libvips?(8, 8)
51
- thumbnail_options['no_rotate'] = input_options.fetch('no_rotate', false) if content.mime_type == 'image/jpeg'
53
+ thumbnail_options["no_rotate"] = input_options.fetch("no_rotate", false) if content.mime_type == "image/jpeg"
52
54
  else
53
- thumbnail_options['auto_rotate'] = input_options.fetch('autorotate', true) if content.mime_type == 'image/jpeg'
55
+ thumbnail_options["auto_rotate"] = input_options.fetch("autorotate", true) if content.mime_type == "image/jpeg"
54
56
  end
55
- thumbnail_options['height'] = thumbnail_options.fetch('height', dimensions.height.ceil)
56
- thumbnail_options['import_profile'] = CMYK_PROFILE_PATH if img.get('interpretation') == :cmyk
57
- thumbnail_options['size'] ||= case geometry
58
- when />\z/ then :down # do_not_resize_if_image_smaller_than_requested
59
- when /<\z/ then :up # do_not_resize_if_image_larger_than_requested
60
- else :both
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 == 'application/pdf'
65
+ filename += "[page=#{input_options[:page]}]" if content.mime_type == "application/pdf"
64
66
 
65
- thumbnail_options = thumbnail_options.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v } # symbolize
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))
69
+
70
+ if output_options.include?("profile")
71
+ thumb = thumb.icc_transform(
72
+ output_options["profile"],
73
+ embedded: true,
74
+ intent: :relative,
75
+ black_point_compensation: true
76
+ )
77
+ end
67
78
 
68
79
  content.update(
69
- thumb.write_to_buffer(".#{format}", DragonflyLibvips.symbolize_keys(output_options)),
70
- 'name' => "temp.#{format}",
71
- 'format' => format
80
+ thumb.write_to_buffer(".#{format}", **DragonflyLibvips.symbolize_keys(output_options)),
81
+ "name" => "temp.#{format}",
82
+ "format" => format
72
83
  )
73
84
  content.ext = format
74
85
  end
75
86
 
76
87
  def update_url(url_attributes, _, options = {})
77
- options = options.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v } # stringify keys
78
- return unless format = options.fetch('format', nil)
88
+ options = options.transform_keys { |k| k.to_s } # stringify keys
89
+ return unless format = options.fetch("format", nil)
79
90
  url_attributes.ext = format
80
91
  end
81
92
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DragonflyLibvips
2
- VERSION = '2.5.0'.freeze
4
+ VERSION = "2.6.0"
3
5
  end
@@ -1,15 +1,17 @@
1
- require 'dragonfly'
2
- require 'dragonfly_libvips/dimensions'
3
- require 'dragonfly_libvips/plugin'
4
- require 'dragonfly_libvips/version'
5
- require 'vips'
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('../vendor/cmyk.icm', __dir__)
12
- EPROFILE_PATH = File.expand_path('../vendor/sRGB_v4_ICC_preference.icc', __dir__)
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,42 @@ 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[avif bmp dz gif hdr webp heic heif]
37
-
38
- private
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
+ ]
39
56
 
40
- def self.stringify_keys(hash = {})
41
- hash.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v }
57
+ class << self
58
+ # Controls whether output images automatically get an ICC profile attached
59
+ attr_accessor :auto_profile
42
60
  end
43
61
 
44
- def self.symbolize_keys(hash = {})
45
- hash.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
46
- end
62
+ self.auto_profile ||= true
63
+
64
+ private
65
+ def self.stringify_keys(hash = {})
66
+ hash.transform_keys { |k| k.to_s }
67
+ end
68
+
69
+ def self.symbolize_keys(hash = {})
70
+ hash.transform_keys { |k| k.to_sym }
71
+ end
47
72
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dragonfly_libvips
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Celizna
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2022-07-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: dragonfly
@@ -44,6 +43,20 @@ dependencies:
44
43
  - - ">="
45
44
  - !ruby/object:Gem::Version
46
45
  version: 2.0.16
46
+ - !ruby/object:Gem::Dependency
47
+ name: base64
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
47
60
  - !ruby/object:Gem::Dependency
48
61
  name: bundler
49
62
  requirement: !ruby/object:Gem::Requirement
@@ -132,24 +145,53 @@ dependencies:
132
145
  name: rake
133
146
  requirement: !ruby/object:Gem::Requirement
134
147
  requirements:
135
- - - "~>"
148
+ - - ">="
136
149
  - !ruby/object:Gem::Version
137
- version: '10.0'
150
+ version: '0'
138
151
  type: :development
139
152
  prerelease: false
140
153
  version_requirements: !ruby/object:Gem::Requirement
141
154
  requirements:
142
- - - "~>"
155
+ - - ">="
143
156
  - !ruby/object:Gem::Version
144
- version: '10.0'
145
- description:
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: lefthook
160
+ requirement: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ type: :development
166
+ prerelease: false
167
+ version_requirements: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ - !ruby/object:Gem::Dependency
173
+ name: rubocop-rails_config
174
+ requirement: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ type: :development
180
+ prerelease: false
181
+ version_requirements: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
146
186
  email:
147
187
  - tomas.celizna@gmail.com
148
188
  executables: []
149
189
  extensions: []
150
190
  extra_rdoc_files: []
151
191
  files:
192
+ - ".github/workflows/test.yml"
152
193
  - ".gitignore"
194
+ - ".rubocop.yml"
153
195
  - ".ruby-version"
154
196
  - ".tool-versions"
155
197
  - ".travis.yml"
@@ -162,6 +204,7 @@ files:
162
204
  - bin/console
163
205
  - bin/setup
164
206
  - dragonfly_libvips.gemspec
207
+ - lefthook.yml
165
208
  - lib/dragonfly_libvips.rb
166
209
  - lib/dragonfly_libvips/analysers/image_properties.rb
167
210
  - lib/dragonfly_libvips/dimensions.rb
@@ -187,7 +230,6 @@ homepage: https://github.com/tomasc/dragonfly_libvips
187
230
  licenses:
188
231
  - MIT
189
232
  metadata: {}
190
- post_install_message:
191
233
  rdoc_options: []
192
234
  require_paths:
193
235
  - lib
@@ -202,8 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
244
  - !ruby/object:Gem::Version
203
245
  version: '0'
204
246
  requirements: []
205
- rubygems_version: 3.0.3
206
- signing_key:
247
+ rubygems_version: 3.6.9
207
248
  specification_version: 4
208
249
  summary: Dragonfly analysers and processors for libvips image processing library.
209
250
  test_files: []