rszr 0.8.0 → 1.0.0

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
- SHA1:
3
- metadata.gz: 035d5f7341e71cdc9b5ba70de6e116acd8d8459e
4
- data.tar.gz: 3119e97a26295db8f3931821d6ae835aaa6166ee
2
+ SHA256:
3
+ metadata.gz: ea3437991dd4694e35653020632c3fc360f787e1d391834780fdf118991a90ce
4
+ data.tar.gz: 37ccc3f8693e4fe9d41939cfc2d3786ef72ed24e344059f1dd4e4492efcae862
5
5
  SHA512:
6
- metadata.gz: 003305cff18cc4678a13f238e17d709351a36efea86b5ca2de751d15f933211c0d107601f2be6aa70dfc92a30a87615fdf3372dae26552190d21911451d33445
7
- data.tar.gz: 732e05777cf4adc9c87515e043a226ed42bd56d0c76e3a28bf645fa22b492fed2cb2a473dbdccd4980b76a23b2d7bf579ec45c68a305a07c77f890697ff82e66
6
+ metadata.gz: 35b8219e81c0f89e4b51719617c13edf71421d7e3ed4e1998f8e26fc017545da76c5164c0bbd63c16e5c617cfdd4f5cb1f07a8e0bbdc83b7bb90ea7fbbd71907
7
+ data.tar.gz: fd4361d89e0ff577032da1dea39686c035604d98e5b6b935ca8de8f1289bdfe6cf5678c8842406c0b9c5829cfab2c03af8350670638824a99deeb176e4675428
data/README.md CHANGED
@@ -60,6 +60,9 @@ image.width => 400
60
60
  image.height => 300
61
61
  image.dimensions => [400, 300]
62
62
  image.format => "jpeg"
63
+ image[0, 0] => <Rszr::Color::RGBA @red=38, @green=115, @blue=141, @alpha=255>
64
+ image[0, 0].to_hex => "26738dff"
65
+ image[0, 0].to_hex(rgb: true) => "26738d"
63
66
  ```
64
67
 
65
68
  ### Transformations
@@ -68,6 +71,8 @@ For each transformation, there is a bang! and non-bang method.
68
71
  The bang method changes the image in place, while the non-bang method
69
72
  creates a copy of the image in memory.
70
73
 
74
+ #### Resizing
75
+
71
76
  ```ruby
72
77
  # auto height
73
78
  image.resize(400, :auto)
@@ -78,6 +83,22 @@ image.resize(:auto, 300)
78
83
  # scale factor
79
84
  image.resize(0.5)
80
85
 
86
+ # resize to fill
87
+ image.resize(400, 300, crop: true)
88
+
89
+ # resize to fill with gravity
90
+ # where gravity in [:n, :nw, :w, :sw, :w, :se, :e, :ne, :center]
91
+ image.resize(400, 300, crop: gravity)
92
+
93
+ # save memory, do not duplicate instance
94
+ image.resize!(400, :auto)
95
+ ```
96
+
97
+ Check out the [full list and demo of resize options](https://mtgrosser.github.io/rszr/resizing.html)!
98
+
99
+ #### Other transformations
100
+
101
+ ```ruby
81
102
  # crop
82
103
  image.crop(200, 200, 100, 100)
83
104
 
@@ -98,9 +119,6 @@ image.flop
98
119
 
99
120
  # initialize copy
100
121
  image.dup
101
-
102
- # save memory, do not duplicate instance
103
- image.resize!(400, :auto)
104
122
  ```
105
123
 
106
124
  ### Filters
@@ -146,12 +164,12 @@ Rszr.autorotate = true
146
164
 
147
165
  ## Rails / ActiveStorage interface
148
166
 
149
- Rszr provides a drop-in interface to the `image_resizing` gem.
167
+ Rszr provides a drop-in interface to the `image_processing` gem.
150
168
  It is faster than both `mini_magick` and `vips` and way easier to install than the latter.
151
169
 
152
170
  ```ruby
153
171
  # Gemfile
154
- gem 'image_resizing'
172
+ gem 'image_processing'
155
173
  gem 'rszr'
156
174
 
157
175
  # config/initializers/rszr.rb
data/ext/rszr/image.c CHANGED
@@ -140,6 +140,32 @@ static VALUE rszr_image_height(VALUE self)
140
140
  return INT2NUM(height);
141
141
  }
142
142
 
143
+
144
+ static VALUE rszr_image__pixel_get(VALUE self, VALUE rb_x, VALUE rb_y)
145
+ {
146
+ rszr_image_handle * handle;
147
+ Imlib_Color color_return;
148
+ VALUE rb_rgba;
149
+ int x, y;
150
+
151
+ Check_Type(rb_x, T_FIXNUM);
152
+ x = FIX2INT(rb_x);
153
+ Check_Type(rb_y, T_FIXNUM);
154
+ y = FIX2INT(rb_y);
155
+
156
+ Data_Get_Struct(self, rszr_image_handle, handle);
157
+
158
+ imlib_context_set_image(handle->image);
159
+ imlib_image_query_pixel(x, y, &color_return);
160
+
161
+ rb_rgba = rb_ary_new3(4, INT2NUM(color_return.red),
162
+ INT2NUM(color_return.green),
163
+ INT2NUM(color_return.blue),
164
+ INT2NUM(color_return.alpha));
165
+ return rb_rgba;
166
+ }
167
+
168
+
143
169
  /*
144
170
  static VALUE rszr_image_get_quality(VALUE self)
145
171
  {
@@ -309,7 +335,7 @@ static VALUE rszr_image__sharpen_bang(VALUE self, VALUE rb_radius)
309
335
  if (radius >= 0) {
310
336
  imlib_image_sharpen(radius);
311
337
  } else {
312
- imlib_image_blur(radius);
338
+ imlib_image_blur(-radius);
313
339
  }
314
340
 
315
341
  return self;
@@ -475,6 +501,7 @@ void Init_rszr_image()
475
501
  rb_define_private_method(cImage, "_turn!", rszr_image__turn_bang, 1);
476
502
  rb_define_private_method(cImage, "_rotate", rszr_image__rotate, 2);
477
503
  rb_define_private_method(cImage, "_sharpen!", rszr_image__sharpen_bang, 1);
504
+ rb_define_private_method(cImage, "_pixel", rszr_image__pixel_get, 2);
478
505
 
479
506
  rb_define_private_method(cImage, "_save", rszr_image__save, 3);
480
507
  }
data/lib/rszr/color.rb ADDED
@@ -0,0 +1,25 @@
1
+ module Rszr
2
+ module Color
3
+
4
+ class RGBA
5
+ attr_reader :red, :green, :blue, :alpha
6
+
7
+ def initialize(red, green, blue, alpha = 255)
8
+ if red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255 || alpha < 0 || alpha > 255
9
+ raise ArgumentError, 'color out of range'
10
+ end
11
+ @red, @green, @blue, @alpha = red, green, blue, alpha
12
+ end
13
+
14
+ def to_i(rgb: false)
15
+ i = red.to_i << 24 | green.to_i << 16 | blue.to_i << 8 | alpha.to_i
16
+ rgb ? i >> 8 : i
17
+ end
18
+
19
+ def to_hex(rgb: false)
20
+ "%0#{rgb ? 6 : 8}x" % to_i(rgb: rgb)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
data/lib/rszr/image.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module Rszr
2
2
  class Image
3
+ GRAVITIES = [true, :center, :n, :nw, :w, :sw, :s, :se, :e, :ne].freeze
4
+
3
5
  extend Identification
4
6
  include Buffered
5
7
  include Orientation
@@ -37,6 +39,12 @@ module Rszr
37
39
  fmt = fmt.to_s if fmt.is_a?(Symbol)
38
40
  self._format = fmt
39
41
  end
42
+
43
+ def [](x, y)
44
+ if x >= 0 && x <= width - 1 && y >= 0 && y <= height - 1
45
+ Color::RGBA.new(*_pixel(x, y))
46
+ end
47
+ end
40
48
 
41
49
  def inspect
42
50
  fmt = format
@@ -166,47 +174,100 @@ module Rszr
166
174
  # 400, 300, background: rgba
167
175
  # 400, 300, skew: true
168
176
 
169
- def calculate_size(*args, crop: nil, skew: nil)
170
- options = args.last.is_a?(Hash) ? args.pop : {}
177
+ def calculate_size(*args, crop: nil, skew: nil, inflate: true)
178
+ #options = args.last.is_a?(Hash) ? args.pop : {}
171
179
  #assert_valid_keys options, :crop, :background, :skew #:extend, :width, :height, :max_width, :max_height, :box
172
- original_width, original_height = width, height
173
- x, y, = 0, 0
174
180
  if args.size == 1
175
- scale = args.first
176
- raise ArgumentError, "scale factor #{scale.inspect} out of range" unless scale > 0 && scale < 1
177
- new_width = original_width.to_f * scale
178
- new_height = original_height.to_f * scale
181
+ calculate_size_for_scale(args.first)
179
182
  elsif args.size == 2
180
183
  box_width, box_height = args
181
- if :auto == box_width && box_height.is_a?(Numeric)
182
- new_height = box_height
183
- new_width = box_height.to_f / original_height.to_f * original_width.to_f
184
- elsif box_width.is_a?(Numeric) && :auto == box_height
185
- new_width = box_width
186
- new_height = box_width.to_f / original_width.to_f * original_height.to_f
184
+ if args.include?(:auto)
185
+ calculate_size_for_auto(box_width, box_height)
187
186
  elsif box_width.is_a?(Numeric) && box_height.is_a?(Numeric)
188
- if skew
189
- new_width, new_height = box_width, box_height
187
+ if not inflate and width <= box_width and height <= box_height
188
+ [0, 0, width, height, width, height]
189
+ elsif skew
190
+ calculate_size_for_skew(box_width, box_height)
190
191
  elsif crop
191
- # TODO: calculate x, y offset if crop
192
+ calculate_size_for_crop(box_width, box_height, crop)
192
193
  else
193
- scale = original_width.to_f / original_height.to_f
194
- box_scale = box_width.to_f / box_height.to_f
195
- if scale >= box_scale # wider
196
- new_width = box_width
197
- new_height = original_height.to_f * box_width.to_f / original_width.to_f
198
- else # narrower
199
- new_height = box_height
200
- new_width = original_width.to_f * box_height.to_f / original_height.to_f
201
- end
194
+ calculate_size_for_limit(box_width, box_height)
202
195
  end
203
- else
204
- raise ArgumentError, "unconclusive arguments #{args.inspect} #{options.inspect}"
205
196
  end
206
197
  else
207
198
  raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
208
199
  end
209
- [x, y, original_width, original_height, new_width.round, new_height.round]
200
+ end
201
+
202
+ def calculate_size_for_scale(factor)
203
+ raise ArgumentError, "scale factor #{factor.inspect} out of range" unless factor > 0 && factor < 1
204
+ [0, 0, width, height, (width.to_f * factor).round, (height.to_f * factor).round]
205
+ end
206
+
207
+ def calculate_size_for_skew(box_width, box_height)
208
+ [0, 0, width, height, box_width, box_height]
209
+ end
210
+
211
+ def calculate_size_for_auto(box_width, box_height)
212
+ if :auto == box_width && box_height.is_a?(Numeric)
213
+ new_height = box_height
214
+ new_width = (box_height.to_f / height.to_f * width.to_f).round
215
+ elsif box_width.is_a?(Numeric) && :auto == box_height
216
+ new_width = box_width
217
+ new_height = (box_width.to_f / width.to_f * height.to_f).round
218
+ else
219
+ raise ArgumentError, "unconclusive arguments #{box_width.inspect}, #{box_height.inspect}"
220
+ end
221
+ [0, 0, width, height, new_width, new_height]
222
+ end
223
+
224
+ def calculate_size_for_crop(box_width, box_height, crop)
225
+ raise ArgumentError, "invalid crop gravity" unless GRAVITIES.include?(crop)
226
+ aspect = width.to_f / height.to_f
227
+ box_aspect = box_width.to_f / box_height.to_f
228
+ if aspect >= box_aspect # wider than box
229
+ src_width = (box_width.to_f * height.to_f / box_height.to_f).round
230
+ src_height = height
231
+ x = crop_horizontally(src_width, crop)
232
+ y = 0
233
+ else # narrower than box
234
+ src_width = width
235
+ src_height = (box_height.to_f * width.to_f / box_width.to_f).round
236
+ x = 0
237
+ y = crop_vertically(src_height, crop)
238
+ end
239
+ [x, y, src_width, src_height, box_width, box_height]
240
+ end
241
+
242
+ def crop_horizontally(src_width, crop)
243
+ case crop
244
+ when :nw, :w, :sw then 0
245
+ when :ne, :e, :se then width - src_width
246
+ else
247
+ ((width - src_width).to_f / 2.to_f).round
248
+ end
249
+ end
250
+
251
+ def crop_vertically(src_height, crop)
252
+ case crop
253
+ when :nw, :n, :ne then 0
254
+ when :sw, :s, :se then height - src_height
255
+ else
256
+ ((height - src_height).to_f / 2.to_f).round
257
+ end
258
+ end
259
+
260
+ def calculate_size_for_limit(box_width, box_height)
261
+ scale = width.to_f / height.to_f
262
+ box_scale = box_width.to_f / box_height.to_f
263
+ if scale >= box_scale # wider
264
+ new_width = box_width
265
+ new_height = (height.to_f * box_width.to_f / width.to_f).round
266
+ else # narrower
267
+ new_height = box_height
268
+ new_width = (width.to_f * box_height.to_f / height.to_f).round
269
+ end
270
+ [0, 0, width, height, new_width, new_height]
210
271
  end
211
272
 
212
273
  def format_from_filename(path)
@@ -51,7 +51,7 @@ module ImageProcessing
51
51
  # Resizes the image to not be larger than the specified dimensions.
52
52
  def resize_to_limit(width, height, **options)
53
53
  width, height = default_dimensions(width, height)
54
- thumbnail(width, height, **options)
54
+ thumbnail(width, height, inflate: false, **options)
55
55
  end
56
56
 
57
57
  # Resizes the image to fit within the specified dimensions.
@@ -62,8 +62,8 @@ module ImageProcessing
62
62
 
63
63
  # Resizes the image to fill the specified dimensions, applying any
64
64
  # necessary cropping.
65
- def resize_to_fill(width, height, **options)
66
- thumbnail(width, height, crop: :center, **options)
65
+ def resize_to_fill(width, height, gravity: :center, **options)
66
+ thumbnail(width, height, crop: gravity, **options)
67
67
  end
68
68
 
69
69
  private
data/lib/rszr/stream.rb CHANGED
@@ -13,7 +13,7 @@ module Rszr
13
13
  raise ArgumentError, "data must be File or String, got #{data.class}"
14
14
  end
15
15
  @data.binmode
16
- @data.seek(start, IO::SEEK_CUR)
16
+ @data.seek(start)
17
17
  @pos = 0
18
18
  end
19
19
 
@@ -33,7 +33,7 @@ module Rszr
33
33
  end
34
34
 
35
35
  def substream
36
- self.class.new(self, pos)
36
+ self.class.new(self, @data.pos)
37
37
  end
38
38
 
39
39
  def fast_forward
data/lib/rszr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rszr
2
- VERSION = '0.8.0'
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/rszr.rb CHANGED
@@ -9,6 +9,7 @@ require 'rszr/stream'
9
9
  require 'rszr/identification'
10
10
  require 'rszr/orientation'
11
11
  require 'rszr/buffered'
12
+ require 'rszr/color'
12
13
  require 'rszr/image'
13
14
 
14
15
  module Rszr
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rszr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-08 00:00:00.000000000 Z
11
+ date: 2021-10-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fast image resizer - do one thing and do it fast.
14
14
  email:
@@ -18,49 +18,49 @@ extensions:
18
18
  - ext/rszr/extconf.rb
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - LICENSE
22
+ - README.md
23
+ - Rakefile
24
+ - ext/rszr/errors.c
25
+ - ext/rszr/errors.h
26
+ - ext/rszr/extconf.rb
27
+ - ext/rszr/image.c
28
+ - ext/rszr/image.h
29
+ - ext/rszr/rszr.c
30
+ - ext/rszr/rszr.h
31
+ - lib/rszr.rb
21
32
  - lib/rszr/batch_transformation.rb
22
33
  - lib/rszr/buffered.rb
34
+ - lib/rszr/color.rb
23
35
  - lib/rszr/identification.rb
24
36
  - lib/rszr/image.rb
25
37
  - lib/rszr/image_processing.rb
26
38
  - lib/rszr/orientation.rb
27
39
  - lib/rszr/stream.rb
28
40
  - lib/rszr/version.rb
29
- - lib/rszr.rb
30
- - ext/rszr/extconf.rb
31
- - ext/rszr/errors.h
32
- - ext/rszr/image.h
33
- - ext/rszr/rszr.h
34
- - ext/rszr/errors.c
35
- - ext/rszr/image.c
36
- - ext/rszr/rszr.c
37
- - LICENSE
38
- - README.md
39
- - Rakefile
40
41
  homepage: https://github.com/mtgrosser/rszr
41
42
  licenses:
42
43
  - MIT
43
44
  metadata: {}
44
- post_install_message:
45
+ post_install_message:
45
46
  rdoc_options: []
46
47
  require_paths:
47
48
  - lib
48
49
  - ext
49
50
  required_ruby_version: !ruby/object:Gem::Requirement
50
51
  requirements:
51
- - - '>='
52
+ - - ">="
52
53
  - !ruby/object:Gem::Version
53
54
  version: '0'
54
55
  required_rubygems_version: !ruby/object:Gem::Requirement
55
56
  requirements:
56
- - - '>='
57
+ - - ">="
57
58
  - !ruby/object:Gem::Version
58
59
  version: '0'
59
60
  requirements:
60
61
  - imlib2
61
- rubyforge_project:
62
- rubygems_version: 2.0.14.1
63
- signing_key:
62
+ rubygems_version: 3.1.4
63
+ signing_key:
64
64
  specification_version: 4
65
65
  summary: Fast image resizer
66
66
  test_files: []