derived_images 0.3.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c8643b74c6c114c37979a7139f55eea2e6ee13925cf307fc0808784151e2b0c
4
- data.tar.gz: 3b41b5bc4754ab82afd4970992a5656dfefca77dec526fe38bb4e3cc81de0611
3
+ metadata.gz: d7495dac1828694cef4a8efc10c27f79841caa93383b2fd87293920a0529b008
4
+ data.tar.gz: '05378013aa550c4007d4c749df0c6208292594dc5b48c86058f06de162b526dc'
5
5
  SHA512:
6
- metadata.gz: 685da6a723ed7dabb55008423f8924c4484da7cdb5ab2499d0c13e5424353df9c6d41cd43c0f9332249e0d713199b2758fab6b12c0c34cca4b7dc4a1065581ac
7
- data.tar.gz: e872970ac4a591925d026c1740e932cdfb912b816f5c3dd1110fd765d814a88bb2558622d06389d51aa89c8027515bf28cbf3bc172b69a9c1dee24781538ba42
6
+ metadata.gz: 41ba0a79e9c02d7961dded202fcb2063b415e4f99ffb1ba8cd7f999600b479d00deeb03b2c7c47b5a2fccf955daa4dc88f98c240d4cb8cff5f29019eab137507
7
+ data.tar.gz: f10af7e4af7e7ee9a912b6e766680ce0ba7414bc3619a0772e49cf8d7db4b6e425e2304f07df9c7c477789cfee89f8c707dd23ccc75742495054604b618ae37e
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DerivedImages
4
+ # A helper class to test for library support for different image formats.
5
+ class FormatSupport
6
+ KNOWN_FORMATS = %w[bmp gif jpg png webp avif heic jp2 jxl].freeze
7
+
8
+ def initialize(processor = DerivedImages.config.processor)
9
+ @processor = processor
10
+ end
11
+
12
+ KNOWN_FORMATS.each do |format|
13
+ define_method("#{format}?") { supports?(format) }
14
+ end
15
+
16
+ alias jpeg_2000? jp2?
17
+ alias jpeg_xl? jxl?
18
+
19
+ def supports?(format)
20
+ if processor == :vips
21
+ vips.include?(format)
22
+ elsif processor == :mini_magick
23
+ magick.include?(format)
24
+ else
25
+ raise "Unknown processor #{processor}"
26
+ end
27
+ end
28
+
29
+ def self.table(processor)
30
+ instance = new(processor)
31
+ %w[BMP GIF JPEG PNG TIFF WebP].map { [_1, true] }.tap do |table|
32
+ table << ['AVIF', instance.avif?]
33
+ table << ['HEIC', instance.heic?]
34
+ table << ['JPEG 2000', instance.jpeg_2000?]
35
+ table << ['JPEG XL', instance.jpeg_xl?]
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :processor
42
+
43
+ def vips
44
+ @vips ||= Vips.get_suffixes.map { _1.delete('.') }
45
+ end
46
+
47
+ def magick
48
+ @magick ||= begin
49
+ output, = MiniMagick::Shell.new.execute(%w[identify -list format])
50
+ lines = output.partition("\n\n").first.lines[2..]
51
+ lines.reject { _1.start_with?(' ' * 10) } # Remove continuation lines
52
+ .map { _1.strip.split(/\s+/, 4) } # split out fields ("Format Module Mode Description")
53
+ .select { |_format, _, mode, _| mode.start_with?('rw') } # Read and write supported
54
+ .map { _1.first.delete('*').downcase }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -8,10 +8,7 @@ module DerivedImages
8
8
  def initialize(source, target)
9
9
  @source = source
10
10
  @target = target
11
- target_ext = File.extname(target)
12
- pipeline = PROCESSORS.fetch(DerivedImages.config.processor).dup
13
- pipeline = pipeline.convert(target_ext) if target_ext.present?
14
- @pipeline = pipeline
11
+ @pipeline = default_pipeline(File.extname(target).delete_prefix('.'))
15
12
  end
16
13
 
17
14
  def ==(other)
@@ -37,7 +34,9 @@ module DerivedImages
37
34
  def cache_key
38
35
  return nil unless source_present?
39
36
 
40
- Digest::SHA256.hexdigest({ source: source_digest, pipeline: options_hash }.to_json)
37
+ Digest::SHA256.hexdigest({ version: DerivedImages::VERSION,
38
+ source: source_digest,
39
+ pipeline: options_hash }.to_json)
41
40
  end
42
41
 
43
42
  def self.empty_pipeline
@@ -45,6 +44,7 @@ module DerivedImages
45
44
  end
46
45
 
47
46
  PROCESSORS = { mini_magick: ImageProcessing::MiniMagick, vips: ImageProcessing::Vips }.freeze
47
+ COMPRESSION_OVERRIDES = { 'avif' => 'av1', 'heic' => 'hevc' }.freeze
48
48
 
49
49
  def target_digest
50
50
  Digest::SHA256.file(target_path).hexdigest
@@ -60,6 +60,17 @@ module DerivedImages
60
60
  Digest::SHA256.file(source_path).hexdigest
61
61
  end
62
62
 
63
+ def default_pipeline(target_ext)
64
+ pipeline = PROCESSORS.fetch(DerivedImages.config.processor).dup
65
+ pipeline = pipeline.convert(target_ext) if target_ext.present?
66
+ vips = pipeline.options[:processor] == ImageProcessing::Vips::Processor
67
+ if vips && !Vips.at_least_libvips?(8, 12) && COMPRESSION_OVERRIDES.key?(target_ext)
68
+ # https://github.com/libvips/libvips/commit/47383b5bfc136f7870c319a1edce4848e177425b
69
+ pipeline = pipeline.saver(compression: COMPRESSION_OVERRIDES.fetch(target_ext))
70
+ end
71
+ pipeline
72
+ end
73
+
63
74
  protected
64
75
 
65
76
  def options_hash
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DerivedImages
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -45,11 +45,13 @@ module DerivedImages
45
45
  end
46
46
 
47
47
  def generate(entry, cache_key)
48
+ target_path = entry.target_path
48
49
  time = Benchmark.realtime do
49
- tempfile = entry.pipeline.loader(fail: true).call(entry.source_path.to_s)
50
- FileUtils.mv(tempfile.path, entry.target_path)
50
+ tempfile = entry.pipeline.call(entry.source_path.to_s)
51
+ File.chmod(0o644, tempfile.path)
52
+ FileUtils.mv(tempfile.path, target_path)
51
53
  end
52
- cache.store(cache_key, entry.target_path)
54
+ cache.store(cache_key, target_path)
53
55
  DerivedImages.config.logger.info("Created #{entry.target} from #{entry.source} in #{time.round(3)}s")
54
56
  end
55
57
  end
@@ -2,9 +2,11 @@
2
2
 
3
3
  require 'image_processing'
4
4
  require 'listen'
5
+ require 'rails'
5
6
 
6
7
  require 'derived_images/cache'
7
8
  require 'derived_images/dsl'
9
+ require 'derived_images/format_support'
8
10
  require 'derived_images/manifest'
9
11
  require 'derived_images/manifest_entry'
10
12
  require 'derived_images/processor'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: derived_images
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Kitson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-26 00:00:00.000000000 Z
11
+ date: 2023-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: image_processing
@@ -65,6 +65,7 @@ files:
65
65
  - lib/derived_images.rb
66
66
  - lib/derived_images/cache.rb
67
67
  - lib/derived_images/dsl.rb
68
+ - lib/derived_images/format_support.rb
68
69
  - lib/derived_images/manifest.rb
69
70
  - lib/derived_images/manifest_entry.rb
70
71
  - lib/derived_images/processor.rb