dynamic_image 2.0.22 → 2.1.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/README.md +1 -0
- data/lib/dynamic_image.rb +3 -1
- data/lib/dynamic_image/controller.rb +32 -8
- data/lib/dynamic_image/errors.rb +6 -0
- data/lib/dynamic_image/image_reader.rb +11 -1
- data/lib/dynamic_image/jobs.rb +3 -0
- data/lib/dynamic_image/jobs/create_variant.rb +18 -0
- data/lib/dynamic_image/processed_image.rb +35 -19
- data/lib/dynamic_image/profiles/sRGB_ICC_v4_Appearance.icc +0 -0
- data/lib/dynamic_image/routing.rb +2 -1
- data/lib/dynamic_image/version.rb +1 -1
- metadata +23 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 814628e7438a06292a2a283be0c88b724a1449327276c2f7ca89656947c690d7
|
4
|
+
data.tar.gz: 8ff9d551e13362514d102cae1c04e61d3374689282715911448019c425c12487
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c52354d7f7100b367b402ea9be16a522872d423e8f1a21f49482bc86eb6223ac9d0c1194979e1d6b49fcfac2352922460aa44395e37adef1ca8cac0c6009e2b6
|
7
|
+
data.tar.gz: 94c370ea4a7ab9fe575ae324f8d50844c6600c5a677efcfe03471703130b4eea7613c5e3ac48d894481a1520484efdae2843ef90e36486f114009aa168681d1e
|
data/README.md
CHANGED
data/lib/dynamic_image.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "mini_exiftool"
|
3
4
|
require "mini_magick"
|
4
5
|
require "dis"
|
5
6
|
require "vector2d"
|
@@ -12,11 +13,12 @@ require "dynamic_image/errors"
|
|
12
13
|
require "dynamic_image/helper"
|
13
14
|
require "dynamic_image/image_reader"
|
14
15
|
require "dynamic_image/image_sizing"
|
16
|
+
require "dynamic_image/jobs"
|
15
17
|
require "dynamic_image/metadata"
|
16
18
|
require "dynamic_image/model"
|
17
19
|
require "dynamic_image/processed_image"
|
18
20
|
require "dynamic_image/routing"
|
19
21
|
|
20
22
|
module DynamicImage
|
21
|
-
cattr_accessor :digest_verifier
|
23
|
+
cattr_accessor :digest_verifier, :process_later_limit
|
22
24
|
end
|
@@ -44,13 +44,39 @@ module DynamicImage
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def cache_expiration_header
|
47
|
-
expires_in 30.days, public: true
|
47
|
+
expires_in 30.days, public: true if response.status == 200
|
48
48
|
end
|
49
49
|
|
50
50
|
def find_record
|
51
51
|
@record = model.find(params[:id])
|
52
52
|
end
|
53
53
|
|
54
|
+
def process_and_send(image, options)
|
55
|
+
processed_image = DynamicImage::ProcessedImage.new(image, options)
|
56
|
+
if process_later?(processed_image, requested_size)
|
57
|
+
process_later(image, options, requested_size)
|
58
|
+
head 503, retry_after: 10
|
59
|
+
else
|
60
|
+
send_image(processed_image, requested_size)
|
61
|
+
end
|
62
|
+
rescue MiniMagick::Error
|
63
|
+
process_later(image, options, requested_size)
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
|
67
|
+
def process_later(image, options, requested_size)
|
68
|
+
DynamicImage::Jobs::CreateVariant
|
69
|
+
.perform_later(image, options, requested_size.to_s)
|
70
|
+
end
|
71
|
+
|
72
|
+
def process_later?(processed_image, size)
|
73
|
+
return false unless DynamicImage.process_later_limit
|
74
|
+
|
75
|
+
image_size = processed_image.record.size.x * processed_image.record.size.y
|
76
|
+
image_size > DynamicImage.process_later_limit &&
|
77
|
+
!processed_image.find_variant(size)
|
78
|
+
end
|
79
|
+
|
54
80
|
def render_image(options)
|
55
81
|
return unless stale?(@record)
|
56
82
|
|
@@ -60,7 +86,7 @@ module DynamicImage
|
|
60
86
|
layout: false, locals: { options: options })
|
61
87
|
end
|
62
88
|
format.any(:gif, :jpeg, :jpg, :png, :tiff, :webp) do
|
63
|
-
|
89
|
+
process_and_send(@record, options)
|
64
90
|
end
|
65
91
|
end
|
66
92
|
end
|
@@ -82,12 +108,10 @@ module DynamicImage
|
|
82
108
|
params[:format]
|
83
109
|
end
|
84
110
|
|
85
|
-
def send_image(processed_image)
|
86
|
-
send_data(
|
87
|
-
|
88
|
-
|
89
|
-
disposition: "inline"
|
90
|
-
)
|
111
|
+
def send_image(processed_image, requested_size)
|
112
|
+
send_data(processed_image.cropped_and_resized(requested_size),
|
113
|
+
content_type: processed_image.content_type,
|
114
|
+
disposition: "inline")
|
91
115
|
end
|
92
116
|
|
93
117
|
def verify_signed_params
|
data/lib/dynamic_image/errors.rb
CHANGED
@@ -3,11 +3,17 @@
|
|
3
3
|
module DynamicImage
|
4
4
|
module Errors
|
5
5
|
class Error < StandardError; end
|
6
|
+
|
6
7
|
class InvalidImage < DynamicImage::Errors::Error; end
|
8
|
+
|
7
9
|
class InvalidHeader < DynamicImage::Errors::Error; end
|
10
|
+
|
8
11
|
class InvalidSignature < DynamicImage::Errors::Error; end
|
12
|
+
|
9
13
|
class InvalidSizeOptions < DynamicImage::Errors::Error; end
|
14
|
+
|
10
15
|
class InvalidTransformation < DynamicImage::Errors::Error; end
|
16
|
+
|
11
17
|
class ParameterMissing < DynamicImage::Errors::Error; end
|
12
18
|
end
|
13
19
|
end
|
@@ -21,6 +21,12 @@ module DynamicImage
|
|
21
21
|
@data = data
|
22
22
|
end
|
23
23
|
|
24
|
+
def exif
|
25
|
+
raise DynamicImage::Errors::InvalidHeader unless valid_header?
|
26
|
+
|
27
|
+
MiniExiftool.new(string_io)
|
28
|
+
end
|
29
|
+
|
24
30
|
def read
|
25
31
|
raise DynamicImage::Errors::InvalidHeader unless valid_header?
|
26
32
|
|
@@ -39,7 +45,11 @@ module DynamicImage
|
|
39
45
|
private
|
40
46
|
|
41
47
|
def file_header
|
42
|
-
@file_header ||=
|
48
|
+
@file_header ||= string_io.read(8)
|
49
|
+
end
|
50
|
+
|
51
|
+
def string_io
|
52
|
+
StringIO.new(@data, "rb")
|
43
53
|
end
|
44
54
|
end
|
45
55
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicImage
|
4
|
+
module Jobs
|
5
|
+
# = Create variant
|
6
|
+
#
|
7
|
+
# Creates an image variant.
|
8
|
+
class CreateVariant < ActiveJob::Base
|
9
|
+
queue_as :dis
|
10
|
+
|
11
|
+
def perform(record, options, size)
|
12
|
+
size_v = Vector2d.parse(size)
|
13
|
+
DynamicImage::ProcessedImage.new(record, options)
|
14
|
+
.find_or_create_variant(size_v)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -6,6 +6,8 @@ module DynamicImage
|
|
6
6
|
# Handles all processing of images. Takes an instance of
|
7
7
|
# +DynamicImage::Model+ as argument.
|
8
8
|
class ProcessedImage
|
9
|
+
attr_reader :record
|
10
|
+
|
9
11
|
def initialize(record, options = {})
|
10
12
|
@record = record
|
11
13
|
@uncropped = options[:uncropped] ? true : false
|
@@ -40,10 +42,24 @@ module DynamicImage
|
|
40
42
|
find_or_create_variant(size).data
|
41
43
|
end
|
42
44
|
|
45
|
+
# Find or create a variant with the given size.
|
46
|
+
def find_or_create_variant(size)
|
47
|
+
find_variant(size) || create_variant(size)
|
48
|
+
rescue ActiveRecord::RecordNotUnique
|
49
|
+
find_variant(size)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Find a variant with the given size.
|
53
|
+
def find_variant(size)
|
54
|
+
return nil unless record.persisted?
|
55
|
+
|
56
|
+
record.variants.find_by(variant_params(size))
|
57
|
+
end
|
58
|
+
|
43
59
|
# Normalizes the image.
|
44
60
|
#
|
45
61
|
# * Applies EXIF rotation
|
46
|
-
# *
|
62
|
+
# * Converts to sRGB
|
47
63
|
# * Strips metadata
|
48
64
|
# * Optimizes GIFs
|
49
65
|
# * Performs format conversion if the requested format is different
|
@@ -59,7 +75,7 @@ module DynamicImage
|
|
59
75
|
process_data do |image|
|
60
76
|
image.combine_options do |combined|
|
61
77
|
combined.auto_orient
|
62
|
-
combined
|
78
|
+
convert_to_srgb(image, combined)
|
63
79
|
yield(combined) if block_given?
|
64
80
|
optimize(combined)
|
65
81
|
end
|
@@ -73,6 +89,14 @@ module DynamicImage
|
|
73
89
|
gif? ? DynamicImage::ImageReader.new(image.coalesce.to_blob).read : image
|
74
90
|
end
|
75
91
|
|
92
|
+
def convert_to_srgb(image, combined)
|
93
|
+
if image.data["profiles"].present? &&
|
94
|
+
exif.colorspacedata&.strip&.downcase == record.colorspace
|
95
|
+
combined.profile(srgb_profile)
|
96
|
+
end
|
97
|
+
combined.colorspace("sRGB") if record.cmyk?
|
98
|
+
end
|
99
|
+
|
76
100
|
def create_variant(size)
|
77
101
|
record.variants.create(
|
78
102
|
variant_params(size).merge(filename: record.filename,
|
@@ -90,10 +114,8 @@ module DynamicImage
|
|
90
114
|
end
|
91
115
|
end
|
92
116
|
|
93
|
-
def
|
94
|
-
|
95
|
-
rescue ActiveRecord::RecordNotUnique
|
96
|
-
record.variants.find_by(variant_params(size))
|
117
|
+
def exif
|
118
|
+
@exif ||= DynamicImage::ImageReader.new(record.data).exif
|
97
119
|
end
|
98
120
|
|
99
121
|
def format
|
@@ -105,7 +127,7 @@ module DynamicImage
|
|
105
127
|
end
|
106
128
|
|
107
129
|
def jpeg?
|
108
|
-
content_type == "image/jpeg"
|
130
|
+
content_type == "image/jpeg"
|
109
131
|
end
|
110
132
|
|
111
133
|
def image_sizing
|
@@ -113,10 +135,6 @@ module DynamicImage
|
|
113
135
|
DynamicImage::ImageSizing.new(record, uncropped: @uncropped)
|
114
136
|
end
|
115
137
|
|
116
|
-
def needs_colorspace_conversion?
|
117
|
-
record.cmyk?
|
118
|
-
end
|
119
|
-
|
120
138
|
def needs_format_conversion?
|
121
139
|
format != record_format
|
122
140
|
end
|
@@ -136,15 +154,9 @@ module DynamicImage
|
|
136
154
|
result
|
137
155
|
end
|
138
156
|
|
139
|
-
attr_reader :record
|
140
|
-
|
141
157
|
def record_format
|
142
|
-
{ "image/bmp" => "BMP",
|
143
|
-
"image/
|
144
|
-
"image/gif" => "GIF",
|
145
|
-
"image/jpeg" => "JPEG",
|
146
|
-
"image/pjpeg" => "JPEG",
|
147
|
-
"image/tiff" => "TIFF",
|
158
|
+
{ "image/bmp" => "BMP", "image/png" => "PNG", "image/gif" => "GIF",
|
159
|
+
"image/jpeg" => "JPEG", "image/pjpeg" => "JPEG", "image/tiff" => "TIFF",
|
148
160
|
"image/webp" => "WEBP" }[record.content_type]
|
149
161
|
end
|
150
162
|
|
@@ -152,6 +164,10 @@ module DynamicImage
|
|
152
164
|
raise DynamicImage::Errors::InvalidImage unless record.valid?
|
153
165
|
end
|
154
166
|
|
167
|
+
def srgb_profile
|
168
|
+
File.join(File.dirname(__FILE__), "profiles/sRGB_ICC_v4_Appearance.icc")
|
169
|
+
end
|
170
|
+
|
155
171
|
def variant_params(size)
|
156
172
|
crop_size, crop_start = image_sizing.crop_geometry(size)
|
157
173
|
|
Binary file
|
@@ -13,8 +13,9 @@ module DynamicImage
|
|
13
13
|
options = {
|
14
14
|
path: "#{resource_name}/:digest(/:size)",
|
15
15
|
constraints: { size: /\d+x\d+/ },
|
16
|
-
only: [
|
16
|
+
only: %i[show]
|
17
17
|
}.merge(options)
|
18
|
+
|
18
19
|
resources resource_name, options do
|
19
20
|
get :uncropped, on: :member
|
20
21
|
get :original, on: :member
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Inge Jørgensen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dis
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.0.6
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: mini_exiftool
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.10'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.10'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: mini_magick
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,6 +169,8 @@ files:
|
|
155
169
|
- lib/dynamic_image/helper.rb
|
156
170
|
- lib/dynamic_image/image_reader.rb
|
157
171
|
- lib/dynamic_image/image_sizing.rb
|
172
|
+
- lib/dynamic_image/jobs.rb
|
173
|
+
- lib/dynamic_image/jobs/create_variant.rb
|
158
174
|
- lib/dynamic_image/metadata.rb
|
159
175
|
- lib/dynamic_image/model.rb
|
160
176
|
- lib/dynamic_image/model/dimensions.rb
|
@@ -162,6 +178,7 @@ files:
|
|
162
178
|
- lib/dynamic_image/model/validations.rb
|
163
179
|
- lib/dynamic_image/model/variants.rb
|
164
180
|
- lib/dynamic_image/processed_image.rb
|
181
|
+
- lib/dynamic_image/profiles/sRGB_ICC_v4_Appearance.icc
|
165
182
|
- lib/dynamic_image/routing.rb
|
166
183
|
- lib/dynamic_image/templates/show.html.erb
|
167
184
|
- lib/dynamic_image/version.rb
|
@@ -170,7 +187,7 @@ homepage: https://github.com/elektronaut/dynamic_image
|
|
170
187
|
licenses:
|
171
188
|
- MIT
|
172
189
|
metadata: {}
|
173
|
-
post_install_message:
|
190
|
+
post_install_message:
|
174
191
|
rdoc_options: []
|
175
192
|
require_paths:
|
176
193
|
- lib
|
@@ -185,8 +202,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
202
|
- !ruby/object:Gem::Version
|
186
203
|
version: '0'
|
187
204
|
requirements: []
|
188
|
-
rubygems_version: 3.1.
|
189
|
-
signing_key:
|
205
|
+
rubygems_version: 3.1.4
|
206
|
+
signing_key:
|
190
207
|
specification_version: 4
|
191
208
|
summary: Rails plugin that simplifies image uploading and processing
|
192
209
|
test_files: []
|