shrine-thumbhash 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +18 -0
- data/Gemfile +13 -0
- data/README.md +72 -0
- data/Rakefile +12 -0
- data/lib/shrine/plugins/image.rb +17 -0
- data/lib/shrine/plugins/image_loader/ruby_vips.rb +47 -0
- data/lib/shrine/plugins/thumbhash/version.rb +9 -0
- data/lib/shrine/plugins/thumbhash.rb +75 -0
- data/shrine-thumbhash.gemspec +37 -0
- data/sig/shrine/plugins/thumbhash.rbs +8 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 56d67f222347d85c3a9a72603effe992cbbf5538fa7aeaf1e63d06859c06064c
|
4
|
+
data.tar.gz: 7d808dd14643b00720a42b6c49bdc5aea910902135d4005c92a601e46c89789d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f5b3fff17ba9bd77a9fa1755018a2a219b0dc87a32e7d868dd468bad3890b90695a7a5985265971fe0598378b792d60d0c4f5ca8911bd2b71e88360442d3498d
|
7
|
+
data.tar.gz: fbc81b2d279f6c169e85fa99b7338fe449fac80e78fc1d55e9d7e609bf3af7168240cf83e7c04c7f5c4509c25ae8dd73f94a7a196146783ab48ff4c0902c7a7f
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
TargetRubyVersion: 2.6
|
4
|
+
|
5
|
+
Layout/LineLength:
|
6
|
+
Max: 120
|
7
|
+
|
8
|
+
Metrics/MethodLength:
|
9
|
+
Enabled: true
|
10
|
+
Max: 15
|
11
|
+
|
12
|
+
Style/StringLiterals:
|
13
|
+
Enabled: true
|
14
|
+
EnforcedStyle: double_quotes
|
15
|
+
|
16
|
+
Style/StringLiteralsInInterpolation:
|
17
|
+
Enabled: true
|
18
|
+
EnforcedStyle: double_quotes
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in shrine-thumbhash.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem "rake", "~> 13.0"
|
9
|
+
gem "rspec", "~> 3.0"
|
10
|
+
gem "rubocop", "~> 1.21"
|
11
|
+
gem "ruby-vips", "~> 2.0"
|
12
|
+
|
13
|
+
gem "shrine", ENV["SHRINE_VERSION"] unless ENV["SHRINE_VERSION"].nil?
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Shrine::Thumbhash
|
2
|
+
|
3
|
+
Shrine plugin for generate Thumbhash from image attachments.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
|
+
|
9
|
+
$ bundle add shrine-thumbhash
|
10
|
+
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
12
|
+
|
13
|
+
$ gem install shrine-thumbhash
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
- [ruby-vips gem](https://rubygems.org/gems/ruby-vips) (default or when you specify `:ruby_vips` to image_loader option)
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require "shrine"
|
22
|
+
require "shrine/storage/memory"
|
23
|
+
require "shrine/plugins/thumbhash"
|
24
|
+
|
25
|
+
Shrine.plugin :thumbhash
|
26
|
+
Shrine.storages[:store] = Shrine::Storage::Memory.new
|
27
|
+
uploader = Shrine.new(:store)
|
28
|
+
|
29
|
+
image = File.open("path/to/image.jpg", binmode: true)
|
30
|
+
uploaded_file = uploader.upload(image)
|
31
|
+
|
32
|
+
uploaded_file.thumbhash
|
33
|
+
# => Base64 encoded thumbhash such as "YJqGPQw7sFlslqhFafSE+Q6oJ1h2iHB2Rw=="
|
34
|
+
uploaded_file.thumbhash_urlsafe
|
35
|
+
# => URLsafe Base64 encoded thumbhash such as "YJqGPQw7sFlslqhFafSE-Q6oJ1h2iHB2Rw=="
|
36
|
+
```
|
37
|
+
|
38
|
+
## Options
|
39
|
+
|
40
|
+
### padding
|
41
|
+
When specify false, thumbhash will be without padding.
|
42
|
+
|
43
|
+
Default: true
|
44
|
+
```ruby
|
45
|
+
Shrine.plugin :thumbhash, padding: false
|
46
|
+
... # omit
|
47
|
+
uploaded_file.thumbhash
|
48
|
+
# => Base64 encoded thumbhash without padding such as "YJqGPQw7sFlslqhFafSE+Q6oJ1h2iHB2Rw"
|
49
|
+
uploaded_file.thumbhash_urlsafe
|
50
|
+
# => URLsafe Base64 encoded thumbhash without padding such as "YJqGPQw7sFlslqhFafSE-Q6oJ1h2iHB2Rw"
|
51
|
+
```
|
52
|
+
|
53
|
+
### image_loader
|
54
|
+
A ruby object be used for loading and resizeing image.
|
55
|
+
When you choose from our implementations, you can specify them by Symbol.
|
56
|
+
|
57
|
+
- `:ruby_vips`
|
58
|
+
|
59
|
+
Default: :ruby_vips
|
60
|
+
|
61
|
+
If you want to use something other than our implementations, you can implement it yourself.
|
62
|
+
See `lib/shrine/plugins/image_loader/ruby_vips.rb`.
|
63
|
+
|
64
|
+
## Development
|
65
|
+
|
66
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
67
|
+
|
68
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
69
|
+
|
70
|
+
## Contributing
|
71
|
+
|
72
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/takayamaki/shrine-thumbhash.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shrine # :nodoc:
|
4
|
+
module Plugins # :nodoc:
|
5
|
+
module Thumbhash # :nodoc:
|
6
|
+
class Image # :nodoc:
|
7
|
+
attr_reader :width, :height, :pixels
|
8
|
+
|
9
|
+
def initialize(width, height, pixels)
|
10
|
+
@width = width
|
11
|
+
@height = height
|
12
|
+
@pixels = pixels
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../image"
|
4
|
+
require "ruby-vips"
|
5
|
+
|
6
|
+
class Shrine # :nodoc:
|
7
|
+
module Plugins # :nodoc:
|
8
|
+
module Thumbhash # :nodoc:
|
9
|
+
module ImageLoader # :nodoc:
|
10
|
+
module RubyVips # :nodoc:
|
11
|
+
def self.call(io)
|
12
|
+
image = load_image(io)
|
13
|
+
image = resize_image(image)
|
14
|
+
Thumbhash::Image.new(
|
15
|
+
image.width,
|
16
|
+
image.height,
|
17
|
+
repack_pixels_to_flattened_rgba_array(image)
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.load_image(io)
|
22
|
+
src = ::Vips::Source.new_from_descriptor(io.fileno)
|
23
|
+
::Vips::Image.new_from_source(src, "")
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.resize_image(image)
|
27
|
+
return image if image.width <= 100 && image.height <= 100
|
28
|
+
|
29
|
+
scale_factor = [100.fdiv(image.width), 100.fdiv(image.height)].min
|
30
|
+
image.resize(scale_factor)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.repack_pixels_to_flattened_rgba_array(image)
|
34
|
+
case image.bands
|
35
|
+
when 3
|
36
|
+
image.to_enum.flat_map { |line| line.flat_map { |rgb| rgb.push(255) } }
|
37
|
+
when 4
|
38
|
+
image.to_enum.flat_map(&:flatten)
|
39
|
+
else
|
40
|
+
raise "Unexpected bands: #{image.bands}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shrine"
|
4
|
+
require "thumbhash"
|
5
|
+
|
6
|
+
class Shrine # :nodoc:
|
7
|
+
module Plugins # :nodoc:
|
8
|
+
module Thumbhash # :nodoc:
|
9
|
+
DEFAULT_OPTIONS = {
|
10
|
+
padding: true,
|
11
|
+
image_loader: :ruby_vips
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def self.configure(uploader, **opts)
|
15
|
+
uploader.opts[:thumbhash] ||= DEFAULT_OPTIONS.dup
|
16
|
+
uploader.opts[:thumbhash].merge!(opts)
|
17
|
+
configure_image_loader(uploader.opts[:thumbhash]) if uploader.opts[:thumbhash][:image_loader_class].nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.configure_image_loader(opts)
|
21
|
+
return unless opts[:image_loader] == :ruby_vips
|
22
|
+
|
23
|
+
require_relative "image_loader/ruby_vips"
|
24
|
+
opts[:image_loader] = Shrine::Plugins::Thumbhash::ImageLoader::RubyVips
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods # :nodoc:
|
28
|
+
def generate_thumbhash(io)
|
29
|
+
image = opts[:thumbhash][:image_loader].call(io)
|
30
|
+
|
31
|
+
::ThumbHash.rgba_to_thumb_hash(
|
32
|
+
image.width,
|
33
|
+
image.height,
|
34
|
+
image.pixels
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module InstanceMethods # :nodoc:
|
40
|
+
def extract_metadata(io, **options)
|
41
|
+
thumbhash = self.class.generate_thumbhash(io)
|
42
|
+
super.merge!(encode_thumbhash_as_base64(thumbhash))
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def encode_thumbhash_as_base64(thumbhash)
|
48
|
+
if self.class.opts[:thumbhash][:padding]
|
49
|
+
{
|
50
|
+
"thumbhash" => Base64.strict_encode64(thumbhash),
|
51
|
+
"thumbhash_urlsafe" => Base64.urlsafe_encode64(thumbhash)
|
52
|
+
}
|
53
|
+
else
|
54
|
+
{
|
55
|
+
"thumbhash" => Base64.strict_encode64(thumbhash).gsub!("=", ""),
|
56
|
+
"thumbhash_urlsafe" => Base64.urlsafe_encode64(thumbhash, padding: false)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module FileMethods # :nodoc:
|
63
|
+
def thumbhash
|
64
|
+
metadata["thumbhash"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def thumbhash_urlsafe
|
68
|
+
metadata["thumbhash_urlsafe"]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
register_plugin(:thumbhash, Thumbhash)
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/shrine/plugins/thumbhash/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "shrine-thumbhash"
|
7
|
+
spec.version = Shrine::Plugins::Thumbhash::VERSION
|
8
|
+
spec.authors = ["takayamaki / fusagiko"]
|
9
|
+
spec.email = ["24884114+takayamaki@users.noreply.github.com"]
|
10
|
+
|
11
|
+
spec.summary = "Shrine plugin for generate Thumbhash from image attachments"
|
12
|
+
spec.homepage = "https://github.com/takayamaki/shrine-thumbhash"
|
13
|
+
spec.required_ruby_version = ">= 2.6"
|
14
|
+
|
15
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/takayamaki/shrine-thumbhash"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/takayamaki/shrine-thumbhash/releases"
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(__dir__) do
|
24
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
# Uncomment to register a new dependency of your gem
|
31
|
+
spec.add_dependency "shrine", "~> 3.0"
|
32
|
+
spec.add_dependency "thumbhash", "~> 0.0.1"
|
33
|
+
|
34
|
+
# For more information and examples about making a new gem, check out our
|
35
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
36
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shrine-thumbhash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- takayamaki / fusagiko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: shrine
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thumbhash
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.1
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- 24884114+takayamaki@users.noreply.github.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".rspec"
|
49
|
+
- ".rubocop.yml"
|
50
|
+
- Gemfile
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/shrine/plugins/image.rb
|
54
|
+
- lib/shrine/plugins/image_loader/ruby_vips.rb
|
55
|
+
- lib/shrine/plugins/thumbhash.rb
|
56
|
+
- lib/shrine/plugins/thumbhash/version.rb
|
57
|
+
- shrine-thumbhash.gemspec
|
58
|
+
- sig/shrine/plugins/thumbhash.rbs
|
59
|
+
homepage: https://github.com/takayamaki/shrine-thumbhash
|
60
|
+
licenses: []
|
61
|
+
metadata:
|
62
|
+
allowed_push_host: https://rubygems.org
|
63
|
+
homepage_uri: https://github.com/takayamaki/shrine-thumbhash
|
64
|
+
source_code_uri: https://github.com/takayamaki/shrine-thumbhash
|
65
|
+
changelog_uri: https://github.com/takayamaki/shrine-thumbhash/releases
|
66
|
+
rubygems_mfa_required: 'true'
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.6'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubygems_version: 3.2.3
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Shrine plugin for generate Thumbhash from image attachments
|
86
|
+
test_files: []
|