neofiles 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/app/controllers/neofiles/images_controller.rb +64 -58
- data/lib/neofiles/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa7c4f908b80a9d8ba5b307b8530d61aca743fe4
|
4
|
+
data.tar.gz: 6777e03478b6e518aa531238d2ef8b4a9922512d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 347e357315fcfd834992b69f2e802fdd96602d0e4ce3e57a733d9061dc1bb39958b936546d4fe04119affffee6bc30d9c4b5c86055a6fba555cb09adffe2ff0d
|
7
|
+
data.tar.gz: a38625dcf3f94134b783150b9d626a12d42f94cad746554789812c266ba91f4cba1a7131c829beb9c8fa29f9be0563719d3ad75077073d190e2af1ccb8bc87c2
|
data/README.md
CHANGED
@@ -76,6 +76,7 @@ Add Neofiles and its dependencies to your gemfile:
|
|
76
76
|
gem 'neofiles'
|
77
77
|
gem 'ruby-imagespec', git: 'git://github.com/dim/ruby-imagespec.git'
|
78
78
|
gem 'mini_magick', '3.7.0'
|
79
|
+
gem 'png_quantizator', '0.2.1'
|
79
80
|
```
|
80
81
|
|
81
82
|
***ruby-imagespec*** is needed to get an image file dimensions & content type.
|
@@ -83,6 +84,9 @@ gem 'mini_magick', '3.7.0'
|
|
83
84
|
***mini_magick*** does resizing & watermarking. Actually it is a lightweight wrapper around command-line utility
|
84
85
|
ImageMagick, which must be installed also. Refer to the gem's description for installation instructions.
|
85
86
|
|
87
|
+
***png_quantizator*** does lossless PNG compression. Actually it is a lightweight wrapper around command-line utility
|
88
|
+
Pngquant, which must be installed also. Refer to the gem's description for installation instructions.
|
89
|
+
|
86
90
|
Also, you must have installed MongoDB with its default driver ***mongoid*** (5 version at least) and Rails framework
|
87
91
|
with HAML templating engine. By default the gem needs `neofiles` mongoid client defined in `config/mongoid.yml`, which
|
88
92
|
can be changed in ***Configuration*** section.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'png_quantizator'
|
2
|
+
|
1
3
|
# Special controller for serving images from the database via single action #show.
|
2
4
|
#
|
3
5
|
class Neofiles::ImagesController < ActionController::Metal
|
@@ -21,9 +23,10 @@ class Neofiles::ImagesController < ActionController::Metal
|
|
21
23
|
# format - resize image to no more than that size, example: '100x200'
|
22
24
|
# crop - if '1' and params[:format] is present, then cut image sides if its aspect ratio differs from
|
23
25
|
# params[:format] (otherwise image aspect ration will be preserved)
|
24
|
-
# quality - output
|
26
|
+
# quality - output quality, integer from 1 till 100 for JPEG input, default is 75
|
27
|
+
# for PNG input any value less than 75 triggers lossless compression using pngquant library
|
25
28
|
# nowm - force returned image to not contain watermark - user must be admin or 403 Forbidden response is returned
|
26
|
-
# @see #admin_or_die
|
29
|
+
# @see #admin_or_die (also this removes the default quality to let admins download image originals)
|
27
30
|
#
|
28
31
|
# Maximum allowed format dimensions are set via Rails.application.config.neofiles.image_max_crop_width/height.
|
29
32
|
#
|
@@ -31,77 +34,41 @@ class Neofiles::ImagesController < ActionController::Metal
|
|
31
34
|
# Rails.application.config.neofiles.watermarker if present.
|
32
35
|
#
|
33
36
|
def show
|
34
|
-
|
35
37
|
# get image
|
36
38
|
image_file = Neofiles::Image.find params[:id]
|
37
39
|
|
38
40
|
# prepare headers
|
39
41
|
data = image_file.data
|
40
42
|
options = {
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
filename: CGI::escape(image_file.filename),
|
44
|
+
type: image_file.content_type || 'image/jpeg',
|
45
|
+
disposition: 'inline',
|
44
46
|
}
|
47
|
+
quality = [[Neofiles::quality_requested(params), 100].min, 1].max if Neofiles::quality_requested?(params)
|
48
|
+
quality ||= 75 unless nowm?(image_file)
|
45
49
|
|
46
|
-
|
47
|
-
watermark_image, watermark_width, watermark_height = data, image_file.width, image_file.height
|
48
|
-
if params[:format].present?
|
50
|
+
image = MiniMagick::Image.read(data)
|
49
51
|
|
52
|
+
if params[:format].present?
|
50
53
|
width, height = params[:format].split('x').map(&:to_i)
|
51
|
-
watermark_width, watermark_height = width, height
|
52
54
|
raise Mongoid::Errors::DocumentNotFound unless width.between?(1, CROP_MAX_WIDTH) and height.between?(1, CROP_MAX_HEIGHT)
|
55
|
+
end
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if
|
60
|
-
# construct ImageMagick call:
|
61
|
-
# 1) resize to WxH, allow the result to be bigger on one side
|
62
|
-
# 2) allign resized to center
|
63
|
-
# 3) cut the extending parts
|
64
|
-
# 4) set quality if requested
|
65
|
-
image.combine_options do |c|
|
66
|
-
c.resize "#{width}x#{height}^"
|
67
|
-
c.gravity 'center'
|
68
|
-
c.extent "#{width}x#{height}"
|
69
|
-
c.quality "#{quality}" if setting_quality
|
70
|
-
end
|
71
|
-
else
|
72
|
-
# no cropping so just resize to fit in WxH, one side can be smaller than requested
|
73
|
-
if image_file.width > width || image_file.height > height
|
74
|
-
image.combine_options do |c|
|
75
|
-
c.resize "#{width}x#{height}"
|
76
|
-
c.quality "#{quality}" if setting_quality
|
77
|
-
end
|
78
|
-
else
|
79
|
-
setting_quality = false
|
80
|
-
watermark_width, watermark_height = image_file.width, image_file.height
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# quality requested, but we didn't have a chance to set it before -> forcibly resave as JPEG
|
85
|
-
if quality && !setting_quality
|
86
|
-
image.format 'jpeg'
|
87
|
-
image.quality quality.to_s
|
88
|
-
end
|
89
|
-
|
90
|
-
# get image bytes and stuff
|
91
|
-
data = image.to_blob
|
92
|
-
watermark_image = image
|
93
|
-
options[:type] = image.mime_type
|
57
|
+
crop_requested = Neofiles.crop_requested? params
|
58
|
+
need_resize_without_crop = width && height && (image_file.width > width || image_file.height > height)
|
59
|
+
|
60
|
+
image.combine_options do |mogrify|
|
61
|
+
resize_image(mogrify, width, height, crop_requested, need_resize_without_crop) if width && height
|
62
|
+
compress_image(mogrify, quality) if quality
|
94
63
|
end
|
95
64
|
|
96
|
-
|
65
|
+
# use pngquant when quality less than 75
|
66
|
+
::PngQuantizator::Image.new(image.path).quantize! if options[:type] == 'image/png' && quality && quality < 75
|
97
67
|
|
98
68
|
# set watermark
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
watermark_width: watermark_width,
|
103
|
-
watermark_height: watermark_height
|
104
|
-
)
|
69
|
+
width, height = image_file.width, image_file.height if !crop_requested && !need_resize_without_crop
|
70
|
+
|
71
|
+
data = set_watermark(image, image_file, width, height)
|
105
72
|
|
106
73
|
# stream image headers & bytes
|
107
74
|
send_file_headers! options
|
@@ -132,4 +99,43 @@ class Neofiles::ImagesController < ActionController::Metal
|
|
132
99
|
raise NotAdminException
|
133
100
|
end
|
134
101
|
end
|
135
|
-
|
102
|
+
|
103
|
+
# Fill mogrify command pipe with resize commands
|
104
|
+
def resize_image(mogrify, width, height, crop_requested, need_resize_without_crop)
|
105
|
+
if crop_requested
|
106
|
+
mogrify.resize "#{width}x#{height}^"
|
107
|
+
mogrify.gravity 'center'
|
108
|
+
mogrify.extent "#{width}x#{height}"
|
109
|
+
elsif need_resize_without_crop
|
110
|
+
mogrify.resize "#{width}x#{height}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Fill mogrify command pipe with compression commands for JPEG and PNG
|
115
|
+
# More information: https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/
|
116
|
+
def compress_image(mogrify, quality)
|
117
|
+
mogrify.quality "#{quality}"
|
118
|
+
mogrify << '-unsharp' << '0.25x0.25+8+0.065'
|
119
|
+
mogrify << '-dither' << 'None'
|
120
|
+
mogrify << '-posterize' << '136'
|
121
|
+
mogrify << '-define' << 'jpeg:fancy-upsampling=off'
|
122
|
+
mogrify << '-define' << 'png:compression-filter=5'
|
123
|
+
mogrify << '-define' << 'png:compression-level=9'
|
124
|
+
mogrify << '-define' << 'png:compression-strategy=1'
|
125
|
+
mogrify << '-define' << 'png:exclude-chunk=all'
|
126
|
+
mogrify << '-interlace' << 'none'
|
127
|
+
mogrify << '-colorspace' << 'sRGB'
|
128
|
+
mogrify.strip
|
129
|
+
end
|
130
|
+
|
131
|
+
# Place watermark on the image, if needed
|
132
|
+
def set_watermark(image, image_file, width, height)
|
133
|
+
Rails.application.config.neofiles.watermarker.(
|
134
|
+
image,
|
135
|
+
no_watermark: nowm?(image_file),
|
136
|
+
watermark_width: width,
|
137
|
+
watermark_height: height
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
data/lib/neofiles/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neofiles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konanykhin Ilya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 3.7.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: png_quantizator
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.2.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.2.1
|
69
83
|
description: 'Library for managing files: creating & storing, linking to file owners,
|
70
84
|
serving files from MongoDB'
|
71
85
|
email:
|