rszr 0.5.3 → 0.7.1

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
  SHA256:
3
- metadata.gz: d7322db19722cd5afc93e887fabe4031fa3a3064949956dc3bac562299918f10
4
- data.tar.gz: 8c03c8922f29d3f7989f427018e7baeb6f09c4c9f561fef1b6a92a80f4042ec8
3
+ metadata.gz: bfbe455a6a95a6fc5161b65c03450e66e3e7165794556abd90cfef22da5a1f32
4
+ data.tar.gz: 1ced66bb5a143f23d55dd1496fc79cf29d58b529138405741f93ba6379e62ba5
5
5
  SHA512:
6
- metadata.gz: 82b7c3ea10061666bacd712c39319ef36f19b2aecce3fa89556c591c0ef6f2cedf10b0fb1ed4ee6ac8613cfb40904b7e42306cd08d247d2653ca3135450244ba
7
- data.tar.gz: 52cac4fe43b0feb24e6fb837fdbed69bb4c91e53807ef5d5821c5ab1793d41a698632e1b342e8b14fed0219db080d05179d37eeb6fcef91e8052b66205c2ab07
6
+ metadata.gz: 007c4d61f001ec86a6be7db860a68edf61f1eac63dfbf1b55afc24e51aa4033248b9224a3706b53c2887555812c0eeaac1d7e62ef66c40e0dd0544c8d67642a3
7
+ data.tar.gz: ef41050b95a085ba6d1fd87c26596e3387a9eb6b248e1d0f741c079dcabaa381912e9c07f28916ff8739df29c903513c0cf78e22384396f5a16384428f6b8014
data/README.md CHANGED
@@ -12,16 +12,17 @@ In your Gemfile:
12
12
  gem 'rszr'
13
13
  ```
14
14
 
15
- ### Imlib2
15
+ ### Imlib2 and libexif
16
16
 
17
- Rszr requires the Imlib2 library to do the heavy lifting.
17
+ Rszr requires the `Imlib2` library to do the heavy lifting.
18
+ `libexif` is required for EXIF auto orientation.
18
19
 
19
20
  #### OS X
20
21
 
21
22
  Using homebrew:
22
23
 
23
24
  ```bash
24
- brew install imlib2
25
+ brew install imlib2 libexif
25
26
  ```
26
27
 
27
28
  #### Linux
@@ -29,11 +30,11 @@ brew install imlib2
29
30
  Using your favourite package manager:
30
31
 
31
32
  ```bash
32
- yum install imlib2 imlib2-devel
33
+ yum install imlib2 imlib2-devel libexif libexif-devel
33
34
  ```
34
35
 
35
36
  ```bash
36
- apt-get install libimlib2 libimlib2-dev
37
+ apt-get install libimlib2 libimlib2-dev libexif libexif-dev
37
38
  ```
38
39
 
39
40
  ## Usage
@@ -99,6 +100,16 @@ image.dimensions => [400, 300]
99
100
  image.format => "jpeg"
100
101
  ```
101
102
 
103
+ ### Image auto orientation
104
+
105
+ ```ruby
106
+ # load and autorotate
107
+ image = Rszr::Image.load('image.jpg', autorotate: true)
108
+
109
+ # auto-rotate by default, for Rails apps put this into an initializer
110
+ Rszr.autorotate = true
111
+ ```
112
+
102
113
  ## Rails / ActiveStorage interface
103
114
 
104
115
  Rszr provides a drop-in interface to the `image_resizing` gem.
data/ext/rszr/errors.c CHANGED
@@ -44,7 +44,7 @@ static void rszr_raise_error_with_message(VALUE rb_error_class, Imlib_Load_Error
44
44
  {
45
45
  int error_index = (int) error - 1;
46
46
  if (error_index < 1 || error_index > RSZR_MAX_ERROR_INDEX)
47
- error_index = 13;
47
+ error_index = RSZR_MAX_ERROR_INDEX;
48
48
  VALUE rb_error = rb_exc_new2(rb_error_class, sRszrErrorMessages[error_index]);
49
49
  rb_exc_raise(rb_error);
50
50
  }
data/ext/rszr/extconf.rb CHANGED
@@ -15,4 +15,11 @@ unless find_library('Imlib2', 'imlib_set_cache_size')
15
15
  abort 'Imlib2 is missing'
16
16
  end
17
17
 
18
+ unless find_library('exif', 'exif_data_new_from_file')
19
+ abort 'libexif is missing'
20
+ end
21
+
22
+ have_library('exif')
23
+ have_header('libexif/exif-data.h')
24
+
18
25
  create_makefile 'rszr/rszr'
data/ext/rszr/image.c CHANGED
@@ -28,6 +28,42 @@ static void rszr_image_deallocate(rszr_image_handle * handle)
28
28
  }
29
29
 
30
30
 
31
+ static void rszr_image_autorotate(Imlib_Image image, char * path)
32
+ {
33
+ ExifData * exifData;
34
+ ExifByteOrder byteOrder;
35
+ ExifEntry * exifEntry;
36
+ int orientation = 0;
37
+ int turns = 0;
38
+
39
+ exifData = exif_data_new_from_file(path);
40
+
41
+ if (exifData) {
42
+ byteOrder = exif_data_get_byte_order(exifData);
43
+ exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
44
+ if (exifEntry) {
45
+ orientation = exif_get_short(exifEntry->data, byteOrder);
46
+ }
47
+ }
48
+
49
+ if (orientation < 2 || orientation > 8) return;
50
+
51
+ imlib_context_set_image(image);
52
+
53
+ if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7) {
54
+ imlib_image_flip_horizontal();
55
+ }
56
+
57
+ if (orientation == 5 || orientation == 6) {
58
+ imlib_image_orientate(1);
59
+ } else if (orientation == 3 || orientation == 4) {
60
+ imlib_image_orientate(2);
61
+ } else if (orientation == 7 || orientation == 8) {
62
+ imlib_image_orientate(3);
63
+ }
64
+ }
65
+
66
+
31
67
  static VALUE rszr_image_s_allocate(VALUE klass)
32
68
  {
33
69
  rszr_image_handle * handle = calloc(1, sizeof(rszr_image_handle));
@@ -50,7 +86,7 @@ static VALUE rszr_image_initialize(VALUE self, VALUE rb_width, VALUE rb_height)
50
86
  }
51
87
 
52
88
 
53
- static VALUE rszr_image_s__load(VALUE klass, VALUE rb_path)
89
+ static VALUE rszr_image_s__load(VALUE klass, VALUE rb_path, VALUE autorotate)
54
90
  {
55
91
  rszr_image_handle * handle;
56
92
  Imlib_Image image;
@@ -68,6 +104,8 @@ static VALUE rszr_image_s__load(VALUE klass, VALUE rb_path)
68
104
  return Qnil;
69
105
  }
70
106
 
107
+ if (RTEST(autorotate)) rszr_image_autorotate(image, path);
108
+
71
109
  oImage = rszr_image_s_allocate(cImage);
72
110
  Data_Get_Struct(oImage, rszr_image_handle, handle);
73
111
  handle->image = image;
@@ -246,7 +284,24 @@ static VALUE rszr_image__rotate(VALUE self, VALUE bang, VALUE rb_angle)
246
284
  }
247
285
  }
248
286
 
249
- /*
287
+
288
+ static VALUE rszr_image_filter_bang(VALUE self, VALUE rb_filter_expr)
289
+ {
290
+ rszr_image_handle * handle;
291
+ Imlib_Image image;
292
+ char * filter_expr;
293
+
294
+ filter_expr = StringValueCStr(rb_filter_expr);
295
+
296
+ Data_Get_Struct(self, rszr_image_handle, handle);
297
+
298
+ imlib_context_set_image(handle->image);
299
+ imlib_apply_filter(filter_expr);
300
+
301
+ return self;
302
+ }
303
+
304
+
250
305
  static VALUE rszr_image__brighten_bang(VALUE self, VALUE rb_brightness)
251
306
  {
252
307
  rszr_image_handle * handle;
@@ -254,12 +309,14 @@ static VALUE rszr_image__brighten_bang(VALUE self, VALUE rb_brightness)
254
309
 
255
310
  brightness = NUM2DBL(rb_brightness);
256
311
 
312
+ Data_Get_Struct(self, rszr_image_handle, handle);
313
+
257
314
  imlib_context_set_image(handle->image);
258
- imlib_modify_color_modifier_brightness(brightness);
315
+ imlib_apply_filter("brightness(10);");
259
316
 
260
317
  return self;
261
318
  }
262
- */
319
+
263
320
 
264
321
  static VALUE rszr_image__sharpen_bang(VALUE self, VALUE rb_radius)
265
322
  {
@@ -419,7 +476,7 @@ void Init_rszr_image()
419
476
  rb_define_alloc_func(cImage, rszr_image_s_allocate);
420
477
 
421
478
  // Class methods
422
- rb_define_private_method(rb_singleton_class(cImage), "_load", rszr_image_s__load, 1);
479
+ rb_define_private_method(rb_singleton_class(cImage), "_load", rszr_image_s__load, 2);
423
480
 
424
481
  // Instance methods
425
482
  rb_define_method(cImage, "initialize", rszr_image_initialize, 2);
@@ -427,6 +484,8 @@ void Init_rszr_image()
427
484
  rb_define_method(cImage, "height", rszr_image_height, 0);
428
485
  rb_define_method(cImage, "format", rszr_image_format_get, 0);
429
486
  rb_define_method(cImage, "dup", rszr_image_dup, 0);
487
+ rb_define_method(cImage, "filter!", rszr_image_filter_bang, 1);
488
+
430
489
  // rb_define_method(cImage, "quality", rszr_image_get_quality, 0);
431
490
  // rb_define_method(cImage, "quality=", rszr_image_set_quality, 1);
432
491
 
@@ -437,7 +496,7 @@ void Init_rszr_image()
437
496
  rb_define_private_method(cImage, "_turn!", rszr_image__turn_bang, 1);
438
497
  rb_define_private_method(cImage, "_rotate", rszr_image__rotate, 2);
439
498
  rb_define_private_method(cImage, "_sharpen!", rszr_image__sharpen_bang, 1);
440
- /* rb_define_private_method(cImage, "_brighten!", rszr_image__brighten_bang, 1); */
499
+ rb_define_private_method(cImage, "_brighten!", rszr_image__brighten_bang, 1);
441
500
 
442
501
  rb_define_private_method(cImage, "_save", rszr_image__save, 3);
443
502
  }
data/ext/rszr/rszr.h CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "ruby.h"
5
5
  #include <Imlib2.h>
6
+ #include <libexif/exif-data.h>
6
7
 
7
8
  extern VALUE mRszr;
8
9
  void Init_rszr();
data/lib/rszr.rb CHANGED
@@ -4,3 +4,17 @@ require 'pathname'
4
4
  require 'rszr/rszr'
5
5
  require 'rszr/version'
6
6
  require 'rszr/image'
7
+
8
+ module Rszr
9
+ class << self
10
+ @@autorotate = nil
11
+
12
+ def autorotate
13
+ @@autorotate
14
+ end
15
+
16
+ def autorotate=(value)
17
+ @@autorotate = !!value
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module Rszr
2
+ class BatchTransformation
3
+ attr_reader :transformations, :image
4
+
5
+ def initialize(path, **opts)
6
+ puts "INITIALIZED BATCH for #{path}"
7
+ @image = path.is_a?(Image) ? path : Image.load(path, **opts)
8
+ @transformations = []
9
+ end
10
+
11
+ Image::Transformations.instance_methods.grep(/\w\z/) do |method|
12
+ define_method method do |*args|
13
+ transformations << [method, args]
14
+ self
15
+ end
16
+ end
17
+
18
+ def call
19
+ transformations.each { |method, args| image.public_send("#{method}!", *args) }
20
+ image
21
+ end
22
+
23
+ end
24
+ end
data/lib/rszr/image.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  module Rszr
2
2
  class Image
3
-
3
+
4
4
  class << self
5
5
 
6
- def load(path, **opts)
6
+ def load(path, autorotate: Rszr.autorotate, **opts)
7
7
  path = path.to_s
8
8
  raise FileNotFound unless File.exist?(path)
9
- _load(path)
9
+ _load(path, autorotate)
10
10
  end
11
11
  alias :open :load
12
12
 
@@ -43,7 +43,7 @@ module Rszr
43
43
  def crop!(x, y, width, height)
44
44
  _crop(true, x, y, width, height)
45
45
  end
46
-
46
+
47
47
  def turn(orientation)
48
48
  dup.turn!(orientation)
49
49
  end
@@ -79,11 +79,36 @@ module Rszr
79
79
  _sharpen!(-radius)
80
80
  end
81
81
 
82
- # TODO
83
- #def brighten!(brightness)
84
- # raise ArgumentError, 'illegal brightness' if brightness > 1 || brightness < -1
85
- # _brighten!(brightness)
86
- #end
82
+ def filter(filter_expr)
83
+ dup.filter!(filter_expr)
84
+ end
85
+
86
+ def brighten!(value, r: nil, g: nil, b: nil, a: nil)
87
+ raise ArgumentError, 'illegal brightness' if value > 1 || value < -1
88
+ filter!("colormod(brightness=#{value.to_f});")
89
+ end
90
+
91
+ def brighten(*args)
92
+ dup.brighten!(*args)
93
+ end
94
+
95
+ def contrast!(value, r: nil, g: nil, b: nil, a: nil)
96
+ raise ArgumentError, 'illegal contrast (must be > 0)' if value < 0
97
+ filter!("colormod(contrast=#{value.to_f});")
98
+ end
99
+
100
+ def contrast(*args)
101
+ dup.contrast!(*args)
102
+ end
103
+
104
+ def gamma!(value, r: nil, g: nil, b: nil, a: nil)
105
+ #raise ArgumentError, 'illegal gamma (must be > 0)' if value < 0
106
+ filter!("colormod(gamma=#{value.to_f});")
107
+ end
108
+
109
+ def gamma(*args)
110
+ dup.gamma!(*args)
111
+ end
87
112
  end
88
113
 
89
114
  include Transformations
@@ -91,7 +116,6 @@ module Rszr
91
116
  def save(path, format: nil, quality: nil)
92
117
  format ||= format_from_filename(path) || self.format || 'jpg'
93
118
  raise ArgumentError, "invalid quality #{quality.inspect}" if quality && !(0..100).cover?(quality)
94
- ensure_path_is_writable(path)
95
119
  _save(path.to_s, format.to_s, quality)
96
120
  end
97
121
 
@@ -112,7 +136,7 @@ module Rszr
112
136
  x, y, = 0, 0
113
137
  if args.size == 1
114
138
  scale = args.first
115
- raise ArgumentError, "scale #{scale.inspect} out of range" unless scale > 0 && scale < 1
139
+ raise ArgumentError, "scale factor #{scale.inspect} out of range" unless scale > 0 && scale < 1
116
140
  new_width = original_width.to_f * scale
117
141
  new_height = original_height.to_f * scale
118
142
  elsif args.size == 2
@@ -147,18 +171,9 @@ module Rszr
147
171
  end
148
172
  [x, y, original_width, original_height, new_width.round, new_height.round]
149
173
  end
150
-
174
+
151
175
  def format_from_filename(path)
152
- File.extname(path)[1..-1]
153
- end
154
-
155
- def ensure_path_is_writable(path)
156
- path = Pathname.new(path)
157
- path.dirname.realpath.writable?
158
- rescue Errno::ENOENT => e
159
- raise SaveError, 'Non-existant path component'
160
- rescue SystemCallError => e
161
- raise SaveError, e.message
176
+ File.extname(path)[1..-1].to_s.downcase
162
177
  end
163
178
 
164
179
  def assert_valid_keys(hsh, *valid_keys)
@@ -47,7 +47,7 @@ module ImageProcessing
47
47
  end
48
48
 
49
49
  end
50
-
50
+
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)
data/lib/rszr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rszr
2
- VERSION = '0.5.3'
2
+ VERSION = '0.7.1'
3
3
  end
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.5.3
4
+ version: 0.7.1
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-03-13 00:00:00.000000000 Z
11
+ date: 2021-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 12.3.3
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 12.3.3
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake-compiler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -197,6 +197,7 @@ files:
197
197
  - ext/rszr/rszr.c
198
198
  - ext/rszr/rszr.h
199
199
  - lib/rszr.rb
200
+ - lib/rszr/batch_transformation.rb
200
201
  - lib/rszr/image.rb
201
202
  - lib/rszr/image_processing.rb
202
203
  - lib/rszr/version.rb
@@ -204,7 +205,7 @@ homepage: https://github.com/mtgrosser/rszr
204
205
  licenses:
205
206
  - MIT
206
207
  metadata: {}
207
- post_install_message:
208
+ post_install_message:
208
209
  rdoc_options: []
209
210
  require_paths:
210
211
  - lib
@@ -220,9 +221,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
221
  - !ruby/object:Gem::Version
221
222
  version: '0'
222
223
  requirements:
223
- - Imlib2
224
+ - imlib2
225
+ - libexif
224
226
  rubygems_version: 3.1.4
225
- signing_key:
227
+ signing_key:
226
228
  specification_version: 4
227
229
  summary: Fast image resizer
228
230
  test_files: []