dynamic_image 2.0.2 → 2.0.3

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
  SHA1:
3
- metadata.gz: dee05cad2916e34c6f71212ac5cc79aca2c40caf
4
- data.tar.gz: 4e7eb46f42e851d3872f8733d033519bdc059167
3
+ metadata.gz: d1600a4e263630c8a9936e6f8309add967434b81
4
+ data.tar.gz: 1ad5ff2c9b894a0fd774797cc64395ed72d7b556
5
5
  SHA512:
6
- metadata.gz: 3078b6597ecd6ccc2b01a6724c06850517f266bfc7e71087bd7f4c1e22fccc107d4554062aa58fac90f47a2b46f70b00aca8e0d870bf9341117649eee2bddbd4
7
- data.tar.gz: 30aeeb19d93a6dac8de7aec60ac06fa4d287410bbc4231fcfadb51efbb59d05b1d0ba4d831f68c6a97132af3979d3c46d71cdba119401b8337b32ad882ce037a
6
+ metadata.gz: 6f60bf400b04b6c8b9b7fe9d59ea967796bd58171fbf258ba326349e128bd35bd50cbe49b779a82e6d7d3db0f70636ff7808d79dae2a1f0d1a4f15b96516bf00
7
+ data.tar.gz: 74063c221b4948e5121f0be2f5b6a8244ed4bb25b9c3a44609cfcab902e648ccfee69697b060bdda5186183061ad950f2e71b9e382d674939d7b1367953b7f20
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
3
 
4
- APP_RAKEFILE = 'spec/internal/Rakefile'.freeze
5
- load 'rails/tasks/engine.rake'
4
+ APP_RAKEFILE = "spec/internal/Rakefile".freeze
5
+ load "rails/tasks/engine.rake"
6
6
 
7
7
  RSpec::Core::RakeTask.new
8
8
 
data/lib/dynamic_image.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'mini_magick'
4
- require 'dis'
5
- require 'vector2d'
3
+ require "mini_magick"
4
+ require "dis"
5
+ require "vector2d"
6
6
 
7
- require 'dynamic_image/belongs_to'
8
- require 'dynamic_image/controller'
9
- require 'dynamic_image/digest_verifier'
10
- require 'dynamic_image/errors'
11
- require 'dynamic_image/helper'
12
- require 'dynamic_image/image_reader'
13
- require 'dynamic_image/image_sizing'
14
- require 'dynamic_image/metadata'
15
- require 'dynamic_image/model'
16
- require 'dynamic_image/processed_image'
17
- require 'dynamic_image/railtie'
18
- require 'dynamic_image/routing'
7
+ require "dynamic_image/belongs_to"
8
+ require "dynamic_image/controller"
9
+ require "dynamic_image/digest_verifier"
10
+ require "dynamic_image/errors"
11
+ require "dynamic_image/helper"
12
+ require "dynamic_image/image_reader"
13
+ require "dynamic_image/image_sizing"
14
+ require "dynamic_image/metadata"
15
+ require "dynamic_image/model"
16
+ require "dynamic_image/processed_image"
17
+ require "dynamic_image/railtie"
18
+ require "dynamic_image/routing"
19
19
 
20
20
  module DynamicImage
21
21
  cattr_accessor :digest_verifier
@@ -35,7 +35,7 @@ module DynamicImage
35
35
  send_data(
36
36
  @record.data,
37
37
  content_type: @record.content_type,
38
- disposition: 'inline'
38
+ disposition: "inline"
39
39
  )
40
40
  end
41
41
  end
@@ -60,7 +60,7 @@ module DynamicImage
60
60
  return unless stale?(@record)
61
61
  respond_to do |format|
62
62
  format.html do
63
- render(file: File.join(File.dirname(__FILE__), 'templates/show'),
63
+ render(file: File.join(File.dirname(__FILE__), "templates/show"),
64
64
  layout: false, locals: { options: options })
65
65
  end
66
66
  format.any(:gif, :jpeg, :png, :tiff) do
@@ -77,14 +77,14 @@ module DynamicImage
77
77
  send_data(
78
78
  image.cropped_and_resized(requested_size),
79
79
  content_type: image.content_type,
80
- disposition: 'inline'
80
+ disposition: "inline"
81
81
  )
82
82
  end
83
83
 
84
84
  def verify_signed_params
85
85
  key = [:action, :id, :size].map do |k|
86
86
  k == :id ? params.require(k).to_i : params.require(k)
87
- end.join('-')
87
+ end.join("-")
88
88
  DynamicImage.digest_verifier.verify(key, params[:digest])
89
89
  end
90
90
  end
@@ -20,7 +20,7 @@ module DynamicImage
20
20
  class DigestVerifier
21
21
  def initialize(secret, options = {})
22
22
  @secret = secret
23
- @digest = options[:digest] || 'SHA1'
23
+ @digest = options[:digest] || "SHA1"
24
24
  end
25
25
 
26
26
  # Generates a digest for a string.
@@ -47,11 +47,11 @@ module DynamicImage
47
47
 
48
48
  res = 0
49
49
  b.each_byte { |byte| res |= byte ^ l.shift }
50
- res == 0
50
+ res.zero?
51
51
  end
52
52
 
53
53
  def generate_digest(data)
54
- require 'openssl' unless defined?(OpenSSL)
54
+ require "openssl" unless defined?(OpenSSL)
55
55
  OpenSSL::HMAC.hexdigest(
56
56
  OpenSSL::Digest.const_get(@digest).new,
57
57
  @secret,
@@ -7,5 +7,6 @@ module DynamicImage
7
7
  class InvalidHeader < DynamicImage::Errors::Error; end
8
8
  class InvalidSignature < DynamicImage::Errors::Error; end
9
9
  class InvalidSizeOptions < DynamicImage::Errors::Error; end
10
+ class InvalidTransformation < DynamicImage::Errors::Error; end
10
11
  end
11
12
  end
@@ -115,7 +115,7 @@ module DynamicImage
115
115
  end
116
116
 
117
117
  def dynamic_image_digest(record, action, size = nil)
118
- key = [action || 'show', record.id, size].compact.join('-')
118
+ key = [action || "show", record.id, size].compact.join("-")
119
119
  DynamicImage.digest_verifier.generate(key)
120
120
  end
121
121
 
@@ -152,9 +152,9 @@ module DynamicImage
152
152
  action = options[:action].try(:to_s)
153
153
  size_opts = options.extract!(:size, :crop, :upscale)
154
154
  if size_opts[:size]
155
- image_sizing(record, size_opts, (action == 'uncropped'))
155
+ image_sizing(record, size_opts, (action == "uncropped"))
156
156
  else
157
- (action == 'original' ? record.real_size : record.size).floor.to_s
157
+ (action == "original" ? record.real_size : record.size).floor.to_s
158
158
  end
159
159
  end
160
160
 
@@ -27,21 +27,36 @@ module DynamicImage
27
27
  @file_header ||= StringIO.new(@data, "rb").read(10)
28
28
  end
29
29
 
30
- def magic_bytes
30
+ def gif_magic_bytes
31
31
  [
32
- # GIF
33
32
  "\x47\x49\x46\x38\x37\x61".force_encoding("binary"),
34
- "\x47\x49\x46\x38\x39\x61".force_encoding("binary"),
35
- # PNG
36
- "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a".force_encoding("binary"),
37
- # JPEG
33
+ "\x47\x49\x46\x38\x39\x61".force_encoding("binary")
34
+ ]
35
+ end
36
+
37
+ def jpeg_magic_bytes
38
+ [
38
39
  "\xff\xd8\xff\xdb".force_encoding("binary"),
39
40
  Regexp.new("\xff\xd8\xff\xe0(.*){2}JFIF".force_encoding("binary")),
40
41
  Regexp.new("\xff\xd8\xff\xe1(.*){2}Exif".force_encoding("binary")),
41
- "\xff\xd8\xff\xee\x00\x0e".force_encoding("binary"), # Adobe JPEG
42
- # TIFF
42
+ "\xff\xd8\xff\xee\x00\x0e".force_encoding("binary") # Adobe JPEG
43
+ ]
44
+ end
45
+
46
+ def magic_bytes
47
+ gif_magic_bytes + png_magic_bytes + jpeg_magic_bytes + tiff_magic_bytes
48
+ end
49
+
50
+ def png_magic_bytes
51
+ [
52
+ "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a".force_encoding("binary")
53
+ ]
54
+ end
55
+
56
+ def tiff_magic_bytes
57
+ [
43
58
  "\x49\x49\x2a\x00".force_encoding("binary"),
44
- "\x4d\x4d\x00\x2a".force_encoding("binary"),
59
+ "\x4d\x4d\x00\x2a".force_encoding("binary")
45
60
  ]
46
61
  end
47
62
  end
@@ -16,11 +16,11 @@ module DynamicImage
16
16
  if valid?
17
17
  case metadata[:colorspace]
18
18
  when /rgb/i
19
- 'rgb'
19
+ "rgb"
20
20
  when /cmyk/i
21
- 'cmyk'
21
+ "cmyk"
22
22
  when /gray/i
23
- 'gray'
23
+ "gray"
24
24
  end
25
25
  end
26
26
  end
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'dynamic_image/model/dimensions'
4
- require 'dynamic_image/model/validations'
3
+ require "dynamic_image/model/dimensions"
4
+ require "dynamic_image/model/transformations"
5
+ require "dynamic_image/model/validations"
5
6
 
6
7
  module DynamicImage
7
8
  # = DynamicImage Model
@@ -62,6 +63,7 @@ module DynamicImage
62
63
  extend ActiveSupport::Concern
63
64
  include Dis::Model
64
65
  include DynamicImage::Model::Dimensions
66
+ include DynamicImage::Model::Transformations
65
67
  include DynamicImage::Model::Validations
66
68
 
67
69
  included do
@@ -70,17 +72,17 @@ module DynamicImage
70
72
 
71
73
  # Returns true if the image is in the CMYK colorspace
72
74
  def cmyk?
73
- colorspace == 'cmyk'
75
+ colorspace == "cmyk"
74
76
  end
75
77
 
76
78
  # Returns true if the image is in the grayscale colorspace
77
79
  def gray?
78
- colorspace == 'gray'
80
+ colorspace == "gray"
79
81
  end
80
82
 
81
83
  # Returns true if the image is in the RGB colorspace
82
84
  def rgb?
83
- colorspace == 'rgb'
85
+ colorspace == "rgb"
84
86
  end
85
87
 
86
88
  # Finds a web safe content type. GIF, JPEG and PNG images are allowed,
@@ -89,14 +91,14 @@ module DynamicImage
89
91
  if safe_content_types.include?(content_type)
90
92
  content_type
91
93
  else
92
- 'image/jpeg'
94
+ "image/jpeg"
93
95
  end
94
96
  end
95
97
 
96
98
  # Includes a timestamp fingerprint in the URL param, so
97
99
  # that rendered images can be cached indefinitely.
98
100
  def to_param
99
- [id, updated_at.utc.to_s(cache_timestamp_format)].join('-')
101
+ [id, updated_at.utc.to_s(cache_timestamp_format)].join("-")
100
102
  end
101
103
 
102
104
  private
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ module DynamicImage
4
+ module Model
5
+ # = DynamicImage Model Transformations
6
+ #
7
+ module Transformations
8
+ # Rotates the image
9
+ def rotate(degrees = 90)
10
+ degrees = degrees.to_i % 360
11
+
12
+ return self if degrees.zero?
13
+
14
+ if (degrees % 90).nonzero?
15
+ raise DynamicImage::Errors::InvalidTransformation,
16
+ "angle must be a multiple of 90 degrees"
17
+ end
18
+
19
+ transform_image do |image|
20
+ image.rotate(degrees)
21
+ rotate_dimensions(real_size.x, real_size.y, degrees)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def rotate_dimensions(width, height, degrees)
28
+ (degrees / 90).times do
29
+ width, height = height, width
30
+
31
+ self.real_width = width
32
+ self.real_height = height
33
+
34
+ self.crop_gravity_x, self.crop_gravity_y = rotated_crop_gravity(width)
35
+
36
+ next unless cropped?
37
+
38
+ self.crop_start_x, self.crop_start_y,
39
+ self.crop_width, self.crop_height = rotated_crop(width)
40
+ end
41
+ end
42
+
43
+ def rotated_crop(new_width)
44
+ return nil unless cropped?
45
+ [
46
+ new_width - (crop_start_y + crop_height),
47
+ crop_start_x,
48
+ crop_height,
49
+ crop_width
50
+ ]
51
+ end
52
+
53
+ def rotated_crop_gravity(new_width)
54
+ return nil unless crop_gravity?
55
+ [new_width - crop_gravity_y, crop_gravity_x]
56
+ end
57
+
58
+ def processed_image
59
+ DynamicImage::ProcessedImage.new(self, uncropped: true)
60
+ end
61
+
62
+ def transform_image
63
+ read_image_metadata if data_changed?
64
+ self.data = processed_image.normalized do |image|
65
+ yield(image) if block_given?
66
+ end
67
+ self
68
+ end
69
+ end
70
+ end
71
+ end
@@ -80,7 +80,7 @@ module DynamicImage
80
80
  def validate_crop_bounds
81
81
  required_size = crop_start + crop_size
82
82
  if required_size.x > real_size.x || required_size.y > real_size.y
83
- errors.add(:crop_size, 'is out of bounds')
83
+ errors.add(:crop_size, "is out of bounds")
84
84
  end
85
85
  end
86
86
 
@@ -10,7 +10,7 @@ module DynamicImage
10
10
  @record = record
11
11
  @uncropped = options[:uncropped] ? true : false
12
12
  @format = options[:format].to_s.upcase if options[:format]
13
- @format = 'JPEG' if defined?(@format) && @format == 'JPG'
13
+ @format = "JPEG" if defined?(@format) && @format == "JPG"
14
14
  end
15
15
 
16
16
  # Returns the content type of the processed image.
@@ -62,7 +62,7 @@ module DynamicImage
62
62
  process_data do |image|
63
63
  image.combine_options do |combined|
64
64
  combined.auto_orient
65
- combined.colorspace('sRGB') if needs_colorspace_conversion?
65
+ combined.colorspace("sRGB") if needs_colorspace_conversion?
66
66
  yield(combined) if block_given?
67
67
  optimize(combined)
68
68
  end
@@ -85,7 +85,7 @@ module DynamicImage
85
85
  end
86
86
 
87
87
  def gif?
88
- content_type == 'image/gif'
88
+ content_type == "image/gif"
89
89
  end
90
90
 
91
91
  def image_sizing
@@ -102,7 +102,7 @@ module DynamicImage
102
102
  end
103
103
 
104
104
  def optimize(image)
105
- image.layers 'optimize' if gif?
105
+ image.layers "optimize" if gif?
106
106
  image.strip
107
107
  end
108
108
 
@@ -118,14 +118,14 @@ module DynamicImage
118
118
 
119
119
  def record_format
120
120
  case record.content_type
121
- when 'image/png'
122
- 'PNG'
123
- when 'image/gif'
124
- 'GIF'
125
- when 'image/jpeg', 'image/pjpeg'
126
- 'JPEG'
127
- when 'image/tiff'
128
- 'TIFF'
121
+ when "image/png"
122
+ "PNG"
123
+ when "image/gif"
124
+ "GIF"
125
+ when "image/jpeg", "image/pjpeg"
126
+ "JPEG"
127
+ when "image/tiff"
128
+ "TIFF"
129
129
  end
130
130
  end
131
131
 
@@ -2,11 +2,11 @@
2
2
 
3
3
  module DynamicImage
4
4
  class Railtie < ::Rails::Railtie
5
- initializer 'dynamic_image' do
5
+ initializer "dynamic_image" do
6
6
  ActionDispatch::Routing::Mapper.send :include, DynamicImage::Routing
7
7
 
8
8
  config.after_initialize do |app|
9
- secret = app.key_generator.generate_key('dynamic_image')
9
+ secret = app.key_generator.generate_key("dynamic_image")
10
10
  DynamicImage.digest_verifier = DynamicImage::DigestVerifier.new(secret)
11
11
  end
12
12
 
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module DynamicImage
4
- VERSION = '2.0.2'.freeze
4
+ VERSION = "2.0.3".freeze
5
5
  end
@@ -1,12 +1,12 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rails/generators'
4
- require 'rails/generators/rails/resource/resource_generator'
3
+ require "rails/generators"
4
+ require "rails/generators/rails/resource/resource_generator"
5
5
 
6
6
  module DynamicImage
7
7
  module Generators
8
8
  class ResourceGenerator < Rails::Generators::ResourceGenerator
9
- desc 'Creates a DynamicImage resource'
9
+ desc "Creates a DynamicImage resource"
10
10
 
11
11
  def initialize(args, *options)
12
12
  super(inject_dynamic_image_attributes(args), *options)
@@ -14,10 +14,9 @@ module DynamicImage
14
14
 
15
15
  def add_controller_extension
16
16
  inject_into_file(
17
- File.join(
18
- 'app/controllers',
19
- class_path,
20
- "#{file_name.pluralize}_controller.rb"),
17
+ File.join("app/controllers",
18
+ class_path,
19
+ "#{file_name.pluralize}_controller.rb"),
21
20
  after: "ApplicationController\n"
22
21
  ) do
23
22
  " include DynamicImage::Controller\n\n private\n\n" \
@@ -27,7 +26,7 @@ module DynamicImage
27
26
 
28
27
  def add_model_extension
29
28
  inject_into_file(
30
- File.join('app/models', class_path, "#{file_name}.rb"),
29
+ File.join("app/models", class_path, "#{file_name}.rb"),
31
30
  after: "ActiveRecord::Base\n"
32
31
  ) do
33
32
  " include DynamicImage::Model\n"
@@ -36,7 +35,7 @@ module DynamicImage
36
35
 
37
36
  def alter_resource_routes
38
37
  gsub_file(
39
- File.join('config', 'routes.rb'),
38
+ File.join("config", "routes.rb"),
40
39
  " resources :#{file_name.pluralize}",
41
40
  " image_resources :#{file_name.pluralize}"
42
41
  )
@@ -54,13 +53,13 @@ module DynamicImage
54
53
 
55
54
  def dynamic_image_attributes
56
55
  %w(
57
- content_hash:string content_type:string
56
+ content_hash:string content_type:string
58
57
  content_length:integer
59
58
  filename:string
60
59
  colorspace:string
61
- real_width:integer real_height:integer
62
- crop_width:integer crop_height:integer
63
- crop_start_x:integer crop_start_y:integer
60
+ real_width:integer real_height:integer
61
+ crop_width:integer crop_height:integer
62
+ crop_start_x:integer crop_start_y:integer
64
63
  crop_gravity_x:integer crop_gravity_y:integer
65
64
  )
66
65
  end
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.0.2
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2016-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -127,6 +127,7 @@ files:
127
127
  - lib/dynamic_image/metadata.rb
128
128
  - lib/dynamic_image/model.rb
129
129
  - lib/dynamic_image/model/dimensions.rb
130
+ - lib/dynamic_image/model/transformations.rb
130
131
  - lib/dynamic_image/model/validations.rb
131
132
  - lib/dynamic_image/processed_image.rb
132
133
  - lib/dynamic_image/railtie.rb