dynamic_image 2.0.19 → 2.0.24
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 +4 -4
- data/lib/dynamic_image.rb +1 -0
- data/lib/dynamic_image/belongs_to.rb +1 -1
- data/lib/dynamic_image/controller.rb +21 -10
- data/lib/dynamic_image/engine.rb +11 -1
- data/lib/dynamic_image/image_reader.rb +2 -1
- data/lib/dynamic_image/image_sizing.rb +2 -2
- data/lib/dynamic_image/jobs.rb +3 -0
- data/lib/dynamic_image/jobs/create_variant.rb +18 -0
- data/lib/dynamic_image/model/dimensions.rb +2 -2
- data/lib/dynamic_image/model/validations.rb +2 -1
- data/lib/dynamic_image/processed_image.rb +46 -36
- 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 +43 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6828f7825142e16348273c97f77cda19d191849ff09e545174c8bb445372257e
|
4
|
+
data.tar.gz: 480ebd62de3ddf2a780971b1b63c1ef545dff59f7f54ee1f7ede5ebef33a485b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95279e2367c7f8639be599e3717fd815bcf4f482a59ab3bcafd1e51aac3ce7c86621a1f694a2dfced38473de1b73fde9e7396a085d7e0cc6a335270267ddccfb
|
7
|
+
data.tar.gz: 62e6c9b6b440a51855ae1d5a89bb2b85fab6c126603aa5e0b08f58b372bf7007ddb3e5eb7c9d910a2bb0ee59a0fb217711e706e5adbdb19008f0e97d9ec67087
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
[](https://rubygems.org/gems/dynamic_image)
|
2
|
-
|
2
|
+

|
3
3
|
[](https://codeclimate.com/github/elektronaut/dynamic_image)
|
4
4
|
[](https://codeclimate.com/github/elektronaut/dynamic_image)
|
5
5
|
[](http://inch-ci.org/github/elektronaut/dynamic_image)
|
@@ -15,9 +15,9 @@ uploaded, DynamicImage stores the original file and generates images
|
|
15
15
|
on demand. It handles cropping, resizing, format and colorspace
|
16
16
|
conversion.
|
17
17
|
|
18
|
-
Supported formats at the moment are JPEG, PNG, GIF, BMP and TIFF.
|
19
|
-
|
20
|
-
converted to RGB, and RGB images will be converted to the sRGB
|
18
|
+
Supported formats at the moment are JPEG, PNG, GIF, BMP, WebP and TIFF.
|
19
|
+
BMP, WebP and TIFF images will automatically be converted to JPG. CMYK
|
20
|
+
images will be converted to RGB, and RGB images will be converted to the sRGB
|
21
21
|
colorspace for consistent appearance in all browsers.
|
22
22
|
|
23
23
|
DynamicImage is built on [Dis](https://github.com/elektronaut/dis)
|
data/lib/dynamic_image.rb
CHANGED
@@ -12,6 +12,7 @@ require "dynamic_image/errors"
|
|
12
12
|
require "dynamic_image/helper"
|
13
13
|
require "dynamic_image/image_reader"
|
14
14
|
require "dynamic_image/image_sizing"
|
15
|
+
require "dynamic_image/jobs"
|
15
16
|
require "dynamic_image/metadata"
|
16
17
|
require "dynamic_image/model"
|
17
18
|
require "dynamic_image/processed_image"
|
@@ -8,7 +8,7 @@ module DynamicImage
|
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def belongs_to_image(name, scope = nil, **options)
|
11
|
-
belongs_to(name, scope, options)
|
11
|
+
belongs_to(name, scope, **options)
|
12
12
|
|
13
13
|
define_method "#{name}=" do |new_image|
|
14
14
|
if new_image.present? && !new_image.is_a?(DynamicImage::Model)
|
@@ -44,13 +44,19 @@ 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_later?(processed_image, size)
|
55
|
+
image_size = processed_image.record.size.x * processed_image.record.size.y
|
56
|
+
image_size > 12_500_000 &&
|
57
|
+
!processed_image.find_variant(size)
|
58
|
+
end
|
59
|
+
|
54
60
|
def render_image(options)
|
55
61
|
return unless stale?(@record)
|
56
62
|
|
@@ -59,8 +65,8 @@ module DynamicImage
|
|
59
65
|
render(file: File.join(File.dirname(__FILE__), "templates/show"),
|
60
66
|
layout: false, locals: { options: options })
|
61
67
|
end
|
62
|
-
format.any(:gif, :jpeg, :png, :tiff) do
|
63
|
-
send_image(
|
68
|
+
format.any(:gif, :jpeg, :jpg, :png, :tiff, :webp) do
|
69
|
+
send_image(@record, options)
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
@@ -69,7 +75,7 @@ module DynamicImage
|
|
69
75
|
return unless stale?(@record)
|
70
76
|
|
71
77
|
respond_to do |format|
|
72
|
-
format.any(:gif, :jpeg, :png, :tiff) do
|
78
|
+
format.any(:gif, :jpeg, :jpg, :png, :tiff, :webp) do
|
73
79
|
send_data(@record.data,
|
74
80
|
filename: filename,
|
75
81
|
content_type: @record.content_type,
|
@@ -82,12 +88,17 @@ module DynamicImage
|
|
82
88
|
params[:format]
|
83
89
|
end
|
84
90
|
|
85
|
-
def send_image(
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
+
def send_image(image, options)
|
92
|
+
processed_image = DynamicImage::ProcessedImage.new(image, options)
|
93
|
+
if process_later?(processed_image, requested_size)
|
94
|
+
DynamicImage::Jobs::CreateVariant
|
95
|
+
.perform_later(image, options, requested_size.to_s)
|
96
|
+
head 503, retry_after: 10
|
97
|
+
else
|
98
|
+
send_data(processed_image.cropped_and_resized(requested_size),
|
99
|
+
content_type: processed_image.content_type,
|
100
|
+
disposition: "inline")
|
101
|
+
end
|
91
102
|
end
|
92
103
|
|
93
104
|
def verify_signed_params
|
data/lib/dynamic_image/engine.rb
CHANGED
@@ -17,11 +17,21 @@ module DynamicImage
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
initializer "dynamic_image.mime_types" do
|
21
|
+
Mime::Type.register "image/bmp", :bmp
|
22
|
+
Mime::Type.register "image/gif", :gif
|
23
|
+
Mime::Type.register "image/jpeg", :jpg
|
24
|
+
Mime::Type.register "image/jpeg", :jpeg
|
25
|
+
Mime::Type.register "image/png", :png
|
26
|
+
Mime::Type.register "image/tiff", :tiff
|
27
|
+
Mime::Type.register "image/webp", :webp
|
28
|
+
end
|
29
|
+
|
20
30
|
initializer "dynamic_image.extensions", before: :load_active_support do
|
21
31
|
ActiveSupport.on_load(:active_record) do
|
22
32
|
send :include, DynamicImage::BelongsTo
|
23
33
|
end
|
24
|
-
ActionDispatch::Routing::Mapper.
|
34
|
+
ActionDispatch::Routing::Mapper.include DynamicImage::Routing
|
25
35
|
|
26
36
|
ActionDispatch::ExceptionWrapper.rescue_responses.merge!(
|
27
37
|
"DynamicImage::Errors::InvalidSignature" => :unauthorized
|
@@ -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
|
@@ -70,27 +86,29 @@ module DynamicImage
|
|
70
86
|
private
|
71
87
|
|
72
88
|
def coalesced(image)
|
73
|
-
|
89
|
+
gif? ? DynamicImage::ImageReader.new(image.coalesce.to_blob).read : image
|
90
|
+
end
|
91
|
+
|
92
|
+
def convert_to_srgb(image, combined)
|
93
|
+
combined.profile(srgb_profile) if image.data["profiles"].present?
|
94
|
+
combined.colorspace("sRGB") if record.cmyk?
|
95
|
+
end
|
74
96
|
|
75
|
-
|
97
|
+
def create_variant(size)
|
98
|
+
record.variants.create(
|
99
|
+
variant_params(size).merge(filename: record.filename,
|
100
|
+
content_type: content_type,
|
101
|
+
data: crop_and_resize(size))
|
102
|
+
)
|
76
103
|
end
|
77
104
|
|
78
105
|
def crop_and_resize(size)
|
79
106
|
normalized do |image|
|
80
|
-
|
81
|
-
image.crop(image_sizing.crop_geometry_string(size))
|
82
|
-
image.resize(size)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
107
|
+
next unless record.cropped? || size != record.size
|
86
108
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
variant_params(size).merge(filename: record.filename,
|
91
|
-
content_type: content_type,
|
92
|
-
data: crop_and_resize(size))
|
93
|
-
)
|
109
|
+
image.crop(image_sizing.crop_geometry_string(size))
|
110
|
+
image.resize(size)
|
111
|
+
end
|
94
112
|
end
|
95
113
|
|
96
114
|
def format
|
@@ -102,7 +120,7 @@ module DynamicImage
|
|
102
120
|
end
|
103
121
|
|
104
122
|
def jpeg?
|
105
|
-
content_type == "image/jpeg"
|
123
|
+
content_type == "image/jpeg"
|
106
124
|
end
|
107
125
|
|
108
126
|
def image_sizing
|
@@ -110,10 +128,6 @@ module DynamicImage
|
|
110
128
|
DynamicImage::ImageSizing.new(record, uncropped: @uncropped)
|
111
129
|
end
|
112
130
|
|
113
|
-
def needs_colorspace_conversion?
|
114
|
-
record.cmyk?
|
115
|
-
end
|
116
|
-
|
117
131
|
def needs_format_conversion?
|
118
132
|
format != record_format
|
119
133
|
end
|
@@ -133,30 +147,26 @@ module DynamicImage
|
|
133
147
|
result
|
134
148
|
end
|
135
149
|
|
136
|
-
attr_reader :record
|
137
|
-
|
138
150
|
def record_format
|
139
|
-
{ "image/bmp" => "BMP",
|
140
|
-
"image/
|
141
|
-
"image/
|
142
|
-
"image/jpeg" => "JPEG",
|
143
|
-
"image/pjpeg" => "JPEG",
|
144
|
-
"image/tiff" => "TIFF" }[record.content_type]
|
151
|
+
{ "image/bmp" => "BMP", "image/png" => "PNG", "image/gif" => "GIF",
|
152
|
+
"image/jpeg" => "JPEG", "image/pjpeg" => "JPEG", "image/tiff" => "TIFF",
|
153
|
+
"image/webp" => "WEBP" }[record.content_type]
|
145
154
|
end
|
146
155
|
|
147
156
|
def require_valid_image!
|
148
157
|
raise DynamicImage::Errors::InvalidImage unless record.valid?
|
149
158
|
end
|
150
159
|
|
160
|
+
def srgb_profile
|
161
|
+
File.join(File.dirname(__FILE__), "profiles/sRGB_ICC_v4_Appearance.icc")
|
162
|
+
end
|
163
|
+
|
151
164
|
def variant_params(size)
|
152
165
|
crop_size, crop_start = image_sizing.crop_geometry(size)
|
153
166
|
|
154
|
-
{ width: size.x.round,
|
155
|
-
|
156
|
-
|
157
|
-
crop_height: crop_size.y,
|
158
|
-
crop_start_x: crop_start.x,
|
159
|
-
crop_start_y: crop_start.y,
|
167
|
+
{ width: size.x.round, height: size.y.round,
|
168
|
+
crop_width: crop_size.x, crop_height: crop_size.y,
|
169
|
+
crop_start_x: crop_start.x, crop_start_y: crop_start.y,
|
160
170
|
format: format }
|
161
171
|
end
|
162
172
|
end
|
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,35 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.24
|
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: 2020-
|
11
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.0.6
|
20
17
|
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: '1.1'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.6
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.0.6
|
30
27
|
- - "~>"
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: '1.1'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.6
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: mini_magick
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,6 +78,20 @@ dependencies:
|
|
78
78
|
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: 2.2.1
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rails-controller-testing
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
81
95
|
- !ruby/object:Gem::Dependency
|
82
96
|
name: rspec-rails
|
83
97
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,6 +106,20 @@ dependencies:
|
|
92
106
|
- - "~>"
|
93
107
|
- !ruby/object:Gem::Version
|
94
108
|
version: 3.7.0
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: simplecov
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 0.17.1
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 0.17.1
|
95
123
|
- !ruby/object:Gem::Dependency
|
96
124
|
name: sqlite3
|
97
125
|
requirement: !ruby/object:Gem::Requirement
|
@@ -127,6 +155,8 @@ files:
|
|
127
155
|
- lib/dynamic_image/helper.rb
|
128
156
|
- lib/dynamic_image/image_reader.rb
|
129
157
|
- lib/dynamic_image/image_sizing.rb
|
158
|
+
- lib/dynamic_image/jobs.rb
|
159
|
+
- lib/dynamic_image/jobs/create_variant.rb
|
130
160
|
- lib/dynamic_image/metadata.rb
|
131
161
|
- lib/dynamic_image/model.rb
|
132
162
|
- lib/dynamic_image/model/dimensions.rb
|
@@ -134,6 +164,7 @@ files:
|
|
134
164
|
- lib/dynamic_image/model/validations.rb
|
135
165
|
- lib/dynamic_image/model/variants.rb
|
136
166
|
- lib/dynamic_image/processed_image.rb
|
167
|
+
- lib/dynamic_image/profiles/sRGB_ICC_v4_Appearance.icc
|
137
168
|
- lib/dynamic_image/routing.rb
|
138
169
|
- lib/dynamic_image/templates/show.html.erb
|
139
170
|
- lib/dynamic_image/version.rb
|
@@ -142,7 +173,7 @@ homepage: https://github.com/elektronaut/dynamic_image
|
|
142
173
|
licenses:
|
143
174
|
- MIT
|
144
175
|
metadata: {}
|
145
|
-
post_install_message:
|
176
|
+
post_install_message:
|
146
177
|
rdoc_options: []
|
147
178
|
require_paths:
|
148
179
|
- lib
|
@@ -157,8 +188,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
188
|
- !ruby/object:Gem::Version
|
158
189
|
version: '0'
|
159
190
|
requirements: []
|
160
|
-
rubygems_version: 3.
|
161
|
-
signing_key:
|
191
|
+
rubygems_version: 3.1.2
|
192
|
+
signing_key:
|
162
193
|
specification_version: 4
|
163
194
|
summary: Rails plugin that simplifies image uploading and processing
|
164
195
|
test_files: []
|