rszr 0.5.3 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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: []