neofiles 1.0.4 → 1.0.5

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: d227855f99ea74fc7b13a202cca5d72689fd554c
4
- data.tar.gz: 48e527165016fd379303bcca7913cb236b422f4e
3
+ metadata.gz: aa7c4f908b80a9d8ba5b307b8530d61aca743fe4
4
+ data.tar.gz: 6777e03478b6e518aa531238d2ef8b4a9922512d
5
5
  SHA512:
6
- metadata.gz: b3d5d75d416021bb11f6c21cd60f807341198695080929c68fca7cde77a56740393310633850e7aa5972720642d6ba2210534d90be3ad74c11123c76b2d861b1
7
- data.tar.gz: 18814fd631099783c7f05f37a9bdab996a3a47b67d540aaef16d736a83123da08cd2cd618e32f6bdfe6146a6faf0bf318fc488c193675c17a8db735e195d792d
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 JPEG quality, integer from 1 till 100 (forces JPEG output, otherwise image type is preserved)
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
- filename: CGI::escape(image_file.filename),
42
- type: image_file.content_type || 'image/jpeg',
43
- disposition: 'inline',
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
- # is resizing needed?
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
- quality = [[Neofiles::quality_requested(params), 100].min, 1].max if Neofiles::quality_requested?(params)
55
- setting_quality = quality && options[:type] == 'image/jpeg'
56
-
57
- image = MiniMagick::Image.read(data)
58
-
59
- if Neofiles.crop_requested? params
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
- watermark_image = MiniMagick::Image.read watermark_image unless watermark_image.is_a? MiniMagick::Image
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
- data = Rails.application.config.neofiles.watermarker.(
100
- watermark_image,
101
- no_watermark: nowm?(image_file),
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
- end
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
@@ -1,3 +1,3 @@
1
1
  module Neofiles
2
- VERSION = '1.0.4'
2
+ VERSION = '1.0.5'
3
3
  end
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
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-01-11 00:00:00.000000000 Z
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: