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 +4 -4
- data/README.md +16 -5
- data/ext/rszr/errors.c +1 -1
- data/ext/rszr/extconf.rb +7 -0
- data/ext/rszr/image.c +65 -6
- data/ext/rszr/rszr.h +1 -0
- data/lib/rszr.rb +14 -0
- data/lib/rszr/batch_transformation.rb +24 -0
- data/lib/rszr/image.rb +37 -22
- data/lib/rszr/image_processing.rb +1 -1
- data/lib/rszr/version.rb +1 -1
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfbe455a6a95a6fc5161b65c03450e66e3e7165794556abd90cfef22da5a1f32
|
4
|
+
data.tar.gz: 1ced66bb5a143f23d55dd1496fc79cf29d58b529138405741f93ba6379e62ba5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
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
|
-
|
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,
|
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
|
-
|
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
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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)
|
data/lib/rszr/version.rb
CHANGED
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.
|
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-
|
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:
|
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:
|
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
|
-
-
|
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: []
|