dynamic_image 2.0.19 → 2.0.24

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: b8a443b4bff71c2168b0564f451cbe768ab6c5543e4527e80514e2abc95ec608
4
- data.tar.gz: c30e81b7cb0a61e53de91a6abfbdbddaf9dd9cbc71275377b174f7b4ac225c33
3
+ metadata.gz: 6828f7825142e16348273c97f77cda19d191849ff09e545174c8bb445372257e
4
+ data.tar.gz: 480ebd62de3ddf2a780971b1b63c1ef545dff59f7f54ee1f7ede5ebef33a485b
5
5
  SHA512:
6
- metadata.gz: 1fac29b093705e10f1183269128d4db4874d3a500b2bbc25ae67b03993e0e05228148e548d7f1183766c204ecbb9711857b26dea513653628be7692df85e6aa2
7
- data.tar.gz: 40bf839a47d7ae69b55455b919d16973117b7e7877980802f9c5d3a8b761f7c8460893705b4fa60b08a8e9ea1988265855d6dfdd25a934c89ac3aa1f9a9969dc
6
+ metadata.gz: 95279e2367c7f8639be599e3717fd815bcf4f482a59ab3bcafd1e51aac3ce7c86621a1f694a2dfced38473de1b73fde9e7396a085d7e0cc6a335270267ddccfb
7
+ data.tar.gz: 62e6c9b6b440a51855ae1d5a89bb2b85fab6c126603aa5e0b08f58b372bf7007ddb3e5eb7c9d910a2bb0ee59a0fb217711e706e5adbdb19008f0e97d9ec67087
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [![Version](https://img.shields.io/gem/v/dynamic_image.svg?style=flat)](https://rubygems.org/gems/dynamic_image)
2
- [![Build Status](https://travis-ci.org/elektronaut/dynamic_image.svg?branch=master)](https://travis-ci.org/elektronaut/dynamic_image)
2
+ ![Build](https://github.com/elektronaut/dynamic_image/workflows/Build/badge.svg)
3
3
  [![Code Climate](https://codeclimate.com/github/elektronaut/dynamic_image/badges/gpa.svg)](https://codeclimate.com/github/elektronaut/dynamic_image)
4
4
  [![Code Climate](https://codeclimate.com/github/elektronaut/dynamic_image/badges/coverage.svg)](https://codeclimate.com/github/elektronaut/dynamic_image)
5
5
  [![Inline docs](http://inch-ci.org/github/elektronaut/dynamic_image.svg)](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. The
19
- latter will automatically be converted to JPG. CMYK images will be
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)
@@ -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(DynamicImage::ProcessedImage.new(@record, options))
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(processed_image)
86
- send_data(
87
- processed_image.cropped_and_resized(requested_size),
88
- content_type: processed_image.content_type,
89
- disposition: "inline"
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
@@ -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.send :include, DynamicImage::Routing
34
+ ActionDispatch::Routing::Mapper.include DynamicImage::Routing
25
35
 
26
36
  ActionDispatch::ExceptionWrapper.rescue_responses.merge!(
27
37
  "DynamicImage::Errors::InvalidSignature" => :unauthorized
@@ -11,7 +11,8 @@ module DynamicImage
11
11
  "\xff\xd8", # JPEG
12
12
  "\x49\x49\x2a\x00", # TIFF
13
13
  "\x4d\x4d\x00\x2a",
14
- "\x42\x4d" # BMP
14
+ "\x42\x4d", # BMP
15
+ "\x52\x49\x46\x46" # WEBP
15
16
  ].map { |s| s.dup.force_encoding("binary") }
16
17
  end
17
18
  end
@@ -149,8 +149,8 @@ module DynamicImage
149
149
  @uncropped
150
150
  end
151
151
 
152
- def vector(x, y)
153
- Vector2d.new(x, y)
152
+ def vector(width, height)
153
+ Vector2d.new(width, height)
154
154
  end
155
155
  end
156
156
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dynamic_image/jobs/create_variant"
@@ -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
@@ -82,8 +82,8 @@ module DynamicImage
82
82
 
83
83
  private
84
84
 
85
- def vector(x, y)
86
- Vector2d.new(x, y)
85
+ def vector(width, height)
86
+ Vector2d.new(width, height)
87
87
  end
88
88
  end
89
89
  end
@@ -69,7 +69,8 @@ module DynamicImage
69
69
  image/jpeg
70
70
  image/pjpeg
71
71
  image/png
72
- image/tiff]
72
+ image/tiff
73
+ image/webp]
73
74
  end
74
75
  end
75
76
 
@@ -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
- # * CMYK images are converted to sRGB
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.colorspace("sRGB") if needs_colorspace_conversion?
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
- return image unless gif?
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
- DynamicImage::ImageReader.new(image.coalesce.to_blob).read
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
- if record.cropped? || size != record.size
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
- def find_or_create_variant(size)
88
- record.variants.find_by(variant_params(size)) ||
89
- record.variants.create(
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" || 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/png" => "PNG",
141
- "image/gif" => "GIF",
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
- height: size.y.round,
156
- crop_width: crop_size.x,
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
@@ -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: [:show]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicImage
4
- VERSION = "2.0.19"
4
+ VERSION = "2.0.24"
5
5
  end
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.19
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-02-04 00:00:00.000000000 Z
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.0.1
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: []