rszr 0.4.0 → 0.5.2
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 +5 -5
- data/README.md +15 -2
- data/Rakefile +6 -0
- data/ext/rszr/errors.c +63 -0
- data/ext/rszr/errors.h +15 -0
- data/ext/rszr/extconf.rb +18 -0
- data/ext/rszr/image.c +309 -0
- data/ext/rszr/image.h +12 -0
- data/ext/rszr/rszr.c +17 -0
- data/ext/rszr/rszr.h +10 -0
- data/lib/rszr.rb +1 -7
- data/lib/rszr/image.rb +32 -96
- data/lib/rszr/version.rb +1 -1
- metadata +41 -10
- data/lib/rszr/base.rb +0 -29
- data/lib/rszr/errors.rb +0 -42
- data/lib/rszr/handle.rb +0 -37
- data/lib/rszr/lib.rb +0 -73
- data/lib/rszr/lock.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c4fc21afb848256445e310a0feebab86b2b10ee6baf464bd7e67a44b282b4d07
|
4
|
+
data.tar.gz: bfe92bbc780dbf03135b4b3d7296df141bee74279412b6bd3b6d2ba70362a140
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26d46f7b4d594da5e871d75975d99cd54358bb6585d8b18fbddcba1b4383970099891f7af6d16b51b8dcf19f5ed179b275d001b15f546c3baa58a3b6573613f9
|
7
|
+
data.tar.gz: 0f5866b917277c7afb518fb15ba83451fc7b448681fec26dad4321d17cfa464854e9182cff88008f7ee25b1c6df135f6a14f3980b64a145db9ef93e035de1d9e
|
data/README.md
CHANGED
@@ -45,6 +45,9 @@ image.resize(400, 300)
|
|
45
45
|
# save it
|
46
46
|
image.save('resized.jpg')
|
47
47
|
|
48
|
+
# save it as PNG
|
49
|
+
image.save('resized.png')
|
50
|
+
|
48
51
|
# auto height
|
49
52
|
image.resize(400, :auto)
|
50
53
|
|
@@ -57,18 +60,28 @@ image.resize(0.5)
|
|
57
60
|
# crop
|
58
61
|
image.crop(200, 200, 100, 100)
|
59
62
|
|
63
|
+
# rotate three times 90 deg clockwise
|
64
|
+
image.turn!(3)
|
65
|
+
|
66
|
+
# rotate one time 90 deg counterclockwise
|
67
|
+
image.turn!(-1)
|
68
|
+
|
69
|
+
# initialize copy
|
70
|
+
image.dup
|
71
|
+
|
60
72
|
# save memory, do not duplicate instance
|
61
73
|
image.resize!(400, :auto)
|
62
74
|
|
63
|
-
# image
|
75
|
+
# image info
|
64
76
|
image.width => 400
|
65
77
|
image.height => 300
|
66
78
|
image.dimensions => [400, 300]
|
79
|
+
image.format => "jpeg"
|
67
80
|
```
|
68
81
|
|
69
82
|
## Thread safety
|
70
83
|
|
71
|
-
As of version 0.4.0, Rszr
|
84
|
+
As of version 0.4.0, Rszr is thread safe through the Ruby GIL.
|
72
85
|
Use of any previous versions in a threaded environment is discouraged.
|
73
86
|
|
74
87
|
## Speed
|
data/Rakefile
CHANGED
data/ext/rszr/errors.c
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#ifndef RUBY_RSZR_ERRORS
|
2
|
+
#define RUBY_RSZR_ERRORS
|
3
|
+
|
4
|
+
#include "rszr.h"
|
5
|
+
#include "errors.h"
|
6
|
+
|
7
|
+
VALUE eRszrError = Qnil;
|
8
|
+
VALUE eRszrFileNotFound = Qnil;
|
9
|
+
VALUE eRszrTransformationError = Qnil;
|
10
|
+
VALUE eRszrErrorWithMessage = Qnil;
|
11
|
+
VALUE eRszrLoadError = Qnil;
|
12
|
+
VALUE eRszrSaveError = Qnil;
|
13
|
+
|
14
|
+
static const char * const sRszrErrorMessages[] =
|
15
|
+
{
|
16
|
+
"File does not exist",
|
17
|
+
"File is a directory",
|
18
|
+
"Read permission denied",
|
19
|
+
"Unsupported format",
|
20
|
+
"Path too long",
|
21
|
+
"Non-existant path component",
|
22
|
+
"Path component is not a directory",
|
23
|
+
"Path outside address space",
|
24
|
+
"Too many symbolic links",
|
25
|
+
"Out of memory",
|
26
|
+
"Out of file descriptors",
|
27
|
+
"Write permission denied",
|
28
|
+
"Out of disk space",
|
29
|
+
"Unknown error"
|
30
|
+
};
|
31
|
+
const int RSZR_MAX_ERROR_INDEX = 13;
|
32
|
+
|
33
|
+
void Init_rszr_errors()
|
34
|
+
{
|
35
|
+
eRszrError = rb_define_class_under(mRszr, "Error", rb_eStandardError);
|
36
|
+
eRszrFileNotFound = rb_define_class_under(mRszr, "FileNotFound", eRszrError);
|
37
|
+
eRszrTransformationError = rb_define_class_under(mRszr, "TransformationError", eRszrError);
|
38
|
+
eRszrErrorWithMessage = rb_define_class_under(mRszr, "ErrorWithMessage", eRszrError);
|
39
|
+
eRszrLoadError = rb_define_class_under(mRszr, "LoadError", eRszrErrorWithMessage);
|
40
|
+
eRszrSaveError = rb_define_class_under(mRszr, "SaveError", eRszrErrorWithMessage);
|
41
|
+
}
|
42
|
+
|
43
|
+
static void rszr_raise_error_with_message(VALUE rb_error_class, Imlib_Load_Error error)
|
44
|
+
{
|
45
|
+
int error_index = (int) error - 1;
|
46
|
+
if (error_index < 1 || error_index > RSZR_MAX_ERROR_INDEX)
|
47
|
+
error_index = 13;
|
48
|
+
VALUE rb_error = rb_exc_new2(rb_error_class, sRszrErrorMessages[error_index]);
|
49
|
+
rb_exc_raise(rb_error);
|
50
|
+
}
|
51
|
+
|
52
|
+
void rszr_raise_load_error(Imlib_Load_Error error)
|
53
|
+
{
|
54
|
+
rszr_raise_error_with_message(eRszrLoadError, error);
|
55
|
+
}
|
56
|
+
|
57
|
+
void rszr_raise_save_error(Imlib_Load_Error error)
|
58
|
+
{
|
59
|
+
rszr_raise_error_with_message(eRszrSaveError, error);
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
#endif
|
data/ext/rszr/errors.h
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef RUBY_RSZR_ERRORS_H
|
2
|
+
#define RUBY_RSZR_ERRORS_H
|
3
|
+
|
4
|
+
void Init_rszr_errors();
|
5
|
+
void rszr_raise_load_error(Imlib_Load_Error error);
|
6
|
+
void rszr_raise_save_error(Imlib_Load_Error error);
|
7
|
+
|
8
|
+
extern VALUE eRszrError;
|
9
|
+
extern VALUE eRszrFileNotFound;
|
10
|
+
extern VALUE eRszrTransformationError;
|
11
|
+
extern VALUE eRszrErrorWithMessage;
|
12
|
+
extern VALUE eRszrLoadError;
|
13
|
+
extern VALUE eRszrSaveError;
|
14
|
+
|
15
|
+
#endif
|
data/ext/rszr/extconf.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
imlib2_config = with_config('imlib2-config', 'imlib2-config')
|
5
|
+
|
6
|
+
$CFLAGS << ' -DX_DISPLAY_MISSING ' << `#{imlib2_config} --cflags`.chomp
|
7
|
+
$LDFLAGS << ' ' << `#{imlib2_config} --libs`.chomp
|
8
|
+
$LDFLAGS.gsub!(/\ -lX11\ -lXext/, '') if RUBY_PLATFORM =~ /darwin/
|
9
|
+
|
10
|
+
unless find_header('Imlib2.h')
|
11
|
+
abort 'imlib2 development headers are missing'
|
12
|
+
end
|
13
|
+
|
14
|
+
unless find_library('Imlib2', 'imlib_set_cache_size')
|
15
|
+
abort 'Imlib2 is missing'
|
16
|
+
end
|
17
|
+
|
18
|
+
create_makefile 'rszr/rszr'
|
data/ext/rszr/image.c
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
#ifndef RUBY_RSZR_IMAGE
|
2
|
+
#define RUBY_RSZR_IMAGE
|
3
|
+
|
4
|
+
#include "rszr.h"
|
5
|
+
#include "image.h"
|
6
|
+
#include "errors.h"
|
7
|
+
|
8
|
+
VALUE cImage = Qnil;
|
9
|
+
|
10
|
+
|
11
|
+
static void rszr_free_image(Imlib_Image image)
|
12
|
+
{
|
13
|
+
imlib_context_set_image(image);
|
14
|
+
imlib_free_image();
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
static void rszr_image_deallocate(rszr_image_handle * handle)
|
19
|
+
{
|
20
|
+
// fprintf(stderr, "rszr_image_deallocate");
|
21
|
+
if (handle->image) {
|
22
|
+
// fprintf(stderr, ": freeing");
|
23
|
+
rszr_free_image(handle->image);
|
24
|
+
handle->image = NULL;
|
25
|
+
}
|
26
|
+
free(handle);
|
27
|
+
// fprintf(stderr, "\n");
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
static VALUE rszr_image_s_allocate(VALUE klass)
|
32
|
+
{
|
33
|
+
rszr_image_handle * handle = calloc(1, sizeof(rszr_image_handle));
|
34
|
+
return Data_Wrap_Struct(klass, NULL, rszr_image_deallocate, handle);
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
static VALUE rszr_image_initialize(VALUE self, VALUE rb_width, VALUE rb_height)
|
39
|
+
{
|
40
|
+
rszr_image_handle * handle;
|
41
|
+
|
42
|
+
Check_Type(rb_width, T_FIXNUM);
|
43
|
+
Check_Type(rb_height, T_FIXNUM);
|
44
|
+
|
45
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
46
|
+
|
47
|
+
handle->image = imlib_create_image(FIX2INT(rb_width), FIX2INT(rb_height));
|
48
|
+
|
49
|
+
return self;
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
static VALUE rszr_image_s__load(VALUE klass, VALUE rb_path)
|
54
|
+
{
|
55
|
+
rszr_image_handle * handle;
|
56
|
+
Imlib_Image image;
|
57
|
+
char * path;
|
58
|
+
Imlib_Load_Error error;
|
59
|
+
VALUE oImage;
|
60
|
+
|
61
|
+
path = StringValueCStr(rb_path);
|
62
|
+
|
63
|
+
imlib_set_cache_size(0);
|
64
|
+
image = imlib_load_image_with_error_return(path, &error);
|
65
|
+
|
66
|
+
if (!image) {
|
67
|
+
rszr_raise_load_error(error);
|
68
|
+
return Qnil;
|
69
|
+
}
|
70
|
+
|
71
|
+
oImage = rszr_image_s_allocate(cImage);
|
72
|
+
Data_Get_Struct(oImage, rszr_image_handle, handle);
|
73
|
+
handle->image = image;
|
74
|
+
return oImage;
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
static VALUE rszr_image_format(VALUE self)
|
79
|
+
{
|
80
|
+
rszr_image_handle * handle;
|
81
|
+
char * format;
|
82
|
+
|
83
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
84
|
+
|
85
|
+
imlib_context_set_image(handle->image);
|
86
|
+
format = imlib_image_format();
|
87
|
+
|
88
|
+
if (format) {
|
89
|
+
return rb_str_new2(format);
|
90
|
+
} else {
|
91
|
+
return Qnil;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
static VALUE rszr_image_width(VALUE self)
|
97
|
+
{
|
98
|
+
rszr_image_handle * handle;
|
99
|
+
int width;
|
100
|
+
|
101
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
102
|
+
|
103
|
+
imlib_context_set_image(handle->image);
|
104
|
+
width = imlib_image_get_width();
|
105
|
+
|
106
|
+
return INT2NUM(width);
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
static VALUE rszr_image_height(VALUE self)
|
111
|
+
{
|
112
|
+
rszr_image_handle * handle;
|
113
|
+
int height;
|
114
|
+
|
115
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
116
|
+
|
117
|
+
imlib_context_set_image(handle->image);
|
118
|
+
height = imlib_image_get_height();
|
119
|
+
|
120
|
+
return INT2NUM(height);
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
static VALUE rszr_image_dup(VALUE self)
|
125
|
+
{
|
126
|
+
rszr_image_handle * handle;
|
127
|
+
rszr_image_handle * cloned_handle;
|
128
|
+
Imlib_Image cloned_image;
|
129
|
+
VALUE oClonedImage;
|
130
|
+
|
131
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
132
|
+
|
133
|
+
imlib_context_set_image(handle->image);
|
134
|
+
cloned_image = imlib_clone_image();
|
135
|
+
|
136
|
+
if (!cloned_image) {
|
137
|
+
rb_raise(eRszrTransformationError, "error cloning image");
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
141
|
+
oClonedImage = rszr_image_s_allocate(cImage);
|
142
|
+
Data_Get_Struct(oClonedImage, rszr_image_handle, cloned_handle);
|
143
|
+
cloned_handle->image = cloned_image;
|
144
|
+
|
145
|
+
return oClonedImage;
|
146
|
+
}
|
147
|
+
|
148
|
+
|
149
|
+
static VALUE rszr_image__turn_bang(VALUE self, VALUE orientation)
|
150
|
+
{
|
151
|
+
rszr_image_handle * handle;
|
152
|
+
|
153
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
154
|
+
|
155
|
+
imlib_context_set_image(handle->image);
|
156
|
+
imlib_image_orientate(NUM2INT(orientation));
|
157
|
+
|
158
|
+
return self;
|
159
|
+
}
|
160
|
+
|
161
|
+
|
162
|
+
static Imlib_Image rszr_create_cropped_scaled_image(const Imlib_Image image, VALUE rb_src_x, VALUE rb_src_y, VALUE rb_src_w, VALUE rb_src_h, VALUE rb_dst_w, VALUE rb_dst_h)
|
163
|
+
{
|
164
|
+
Imlib_Image resized_image;
|
165
|
+
|
166
|
+
int src_x = NUM2INT(rb_src_x);
|
167
|
+
int src_y = NUM2INT(rb_src_y);
|
168
|
+
int src_w = NUM2INT(rb_src_w);
|
169
|
+
int src_h = NUM2INT(rb_src_h);
|
170
|
+
int dst_w = NUM2INT(rb_dst_w);
|
171
|
+
int dst_h = NUM2INT(rb_dst_h);
|
172
|
+
|
173
|
+
// TODO: raise if <= 0
|
174
|
+
|
175
|
+
imlib_context_set_image(image);
|
176
|
+
imlib_context_set_anti_alias(1);
|
177
|
+
resized_image = imlib_create_cropped_scaled_image(src_x, src_y, src_w, src_h, dst_w, dst_h);
|
178
|
+
|
179
|
+
if (!resized_image) {
|
180
|
+
rb_raise(eRszrTransformationError, "error resizing image");
|
181
|
+
return NULL;
|
182
|
+
}
|
183
|
+
|
184
|
+
return resized_image;
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
static VALUE rszr_image__resize(VALUE self, VALUE bang, VALUE rb_src_x, VALUE rb_src_y, VALUE rb_src_w, VALUE rb_src_h, VALUE rb_dst_w, VALUE rb_dst_h)
|
189
|
+
{
|
190
|
+
rszr_image_handle * handle;
|
191
|
+
Imlib_Image resized_image;
|
192
|
+
rszr_image_handle * resized_handle;
|
193
|
+
VALUE oResizedImage;
|
194
|
+
|
195
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
196
|
+
|
197
|
+
resized_image = rszr_create_cropped_scaled_image(handle->image, rb_src_x, rb_src_y, rb_src_w, rb_src_h, rb_dst_w, rb_dst_h);
|
198
|
+
if (!resized_image) return Qfalse;
|
199
|
+
|
200
|
+
if (RTEST(bang)) {
|
201
|
+
rszr_free_image(handle->image);
|
202
|
+
handle->image = resized_image;
|
203
|
+
|
204
|
+
return self;
|
205
|
+
}
|
206
|
+
else {
|
207
|
+
oResizedImage = rszr_image_s_allocate(cImage);
|
208
|
+
Data_Get_Struct(oResizedImage, rszr_image_handle, resized_handle);
|
209
|
+
resized_handle->image = resized_image;
|
210
|
+
|
211
|
+
return oResizedImage;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
static Imlib_Image rszr_create_cropped_image(const Imlib_Image image, VALUE rb_x, VALUE rb_y, VALUE rb_w, VALUE rb_h)
|
217
|
+
{
|
218
|
+
Imlib_Image cropped_image;
|
219
|
+
|
220
|
+
int x = NUM2INT(rb_x);
|
221
|
+
int y = NUM2INT(rb_y);
|
222
|
+
int w = NUM2INT(rb_w);
|
223
|
+
int h = NUM2INT(rb_h);
|
224
|
+
|
225
|
+
imlib_context_set_image(image);
|
226
|
+
cropped_image = imlib_create_cropped_image(x, y, w, h);
|
227
|
+
|
228
|
+
if (!cropped_image) {
|
229
|
+
rb_raise(eRszrTransformationError, "error cropping image");
|
230
|
+
return NULL;
|
231
|
+
}
|
232
|
+
|
233
|
+
return cropped_image;
|
234
|
+
}
|
235
|
+
|
236
|
+
|
237
|
+
static VALUE rszr_image__crop(VALUE self, VALUE bang, VALUE rb_x, VALUE rb_y, VALUE rb_w, VALUE rb_h)
|
238
|
+
{
|
239
|
+
rszr_image_handle * handle;
|
240
|
+
Imlib_Image cropped_image;
|
241
|
+
rszr_image_handle * cropped_handle;
|
242
|
+
VALUE oCroppedImage;
|
243
|
+
|
244
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
245
|
+
|
246
|
+
cropped_image = rszr_create_cropped_image(handle->image, rb_x, rb_y, rb_w, rb_h);
|
247
|
+
if (!cropped_image) return Qfalse;
|
248
|
+
|
249
|
+
if (RTEST(bang)) {
|
250
|
+
rszr_free_image(handle->image);
|
251
|
+
handle->image = cropped_image;
|
252
|
+
|
253
|
+
return self;
|
254
|
+
}
|
255
|
+
else {
|
256
|
+
oCroppedImage = rszr_image_s_allocate(cImage);
|
257
|
+
Data_Get_Struct(oCroppedImage, rszr_image_handle, cropped_handle);
|
258
|
+
cropped_handle->image = cropped_image;
|
259
|
+
|
260
|
+
return oCroppedImage;
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
|
265
|
+
static VALUE rszr_image__save(VALUE self, VALUE rb_path, VALUE rb_format)
|
266
|
+
{
|
267
|
+
rszr_image_handle * handle;
|
268
|
+
char * path;
|
269
|
+
char * format;
|
270
|
+
Imlib_Load_Error save_error;
|
271
|
+
|
272
|
+
path = StringValueCStr(rb_path);
|
273
|
+
format = StringValueCStr(rb_format);
|
274
|
+
|
275
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
276
|
+
|
277
|
+
imlib_context_set_image(handle->image);
|
278
|
+
imlib_image_set_format(format);
|
279
|
+
imlib_save_image_with_error_return(path, &save_error);
|
280
|
+
|
281
|
+
if (save_error) {
|
282
|
+
rszr_raise_save_error(save_error);
|
283
|
+
return Qfalse;
|
284
|
+
}
|
285
|
+
|
286
|
+
return Qtrue;
|
287
|
+
}
|
288
|
+
|
289
|
+
void Init_rszr_image()
|
290
|
+
{
|
291
|
+
cImage = rb_define_class_under(mRszr, "Image", rb_cObject);
|
292
|
+
rb_define_alloc_func(cImage, rszr_image_s_allocate);
|
293
|
+
|
294
|
+
// Class methods
|
295
|
+
rb_define_private_method(rb_singleton_class(cImage), "_load", rszr_image_s__load, 1);
|
296
|
+
|
297
|
+
// Instance methods
|
298
|
+
rb_define_method(cImage, "initialize", rszr_image_initialize, 2);
|
299
|
+
rb_define_method(cImage, "width", rszr_image_width, 0);
|
300
|
+
rb_define_method(cImage, "height", rszr_image_height, 0);
|
301
|
+
rb_define_method(cImage, "format", rszr_image_format, 0);
|
302
|
+
rb_define_method(cImage, "dup", rszr_image_dup, 0);
|
303
|
+
rb_define_private_method(cImage, "_resize", rszr_image__resize, 7);
|
304
|
+
rb_define_private_method(cImage, "_crop", rszr_image__crop, 5);
|
305
|
+
rb_define_private_method(cImage, "_turn!", rszr_image__turn_bang, 1);
|
306
|
+
rb_define_private_method(cImage, "_save", rszr_image__save, 2);
|
307
|
+
}
|
308
|
+
|
309
|
+
#endif
|
data/ext/rszr/image.h
ADDED
data/ext/rszr/rszr.c
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef RUBY_RSZR
|
2
|
+
#define RUBY_RSZR
|
3
|
+
|
4
|
+
#include "rszr.h"
|
5
|
+
#include "image.h"
|
6
|
+
#include "errors.h"
|
7
|
+
|
8
|
+
VALUE mRszr = Qnil;
|
9
|
+
|
10
|
+
void Init_rszr()
|
11
|
+
{
|
12
|
+
mRszr = rb_define_module("Rszr");
|
13
|
+
Init_rszr_errors();
|
14
|
+
Init_rszr_image();
|
15
|
+
}
|
16
|
+
|
17
|
+
#endif
|
data/ext/rszr/rszr.h
ADDED
data/lib/rszr.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
|
-
require 'fiddle'
|
2
|
-
require 'fiddle/import'
|
3
1
|
require 'rbconfig'
|
4
2
|
require 'pathname'
|
5
3
|
|
4
|
+
require 'rszr/rszr'
|
6
5
|
require 'rszr/version'
|
7
|
-
require 'rszr/errors'
|
8
|
-
require 'rszr/lib'
|
9
|
-
require 'rszr/lock'
|
10
|
-
require 'rszr/handle'
|
11
|
-
require 'rszr/base'
|
12
6
|
require 'rszr/image'
|
data/lib/rszr/image.rb
CHANGED
@@ -1,97 +1,53 @@
|
|
1
1
|
module Rszr
|
2
2
|
class Image
|
3
|
-
include Base
|
4
3
|
|
5
4
|
class << self
|
6
5
|
|
7
|
-
alias_method :instantiate, :new
|
8
|
-
protected :instantiate
|
9
|
-
|
10
|
-
def new(width, height)
|
11
|
-
ptr = with_lock { imlib_create_image(width, height) }
|
12
|
-
raise Error, 'Could not instantiate image' if ptr.null?
|
13
|
-
instantiate(ptr)
|
14
|
-
end
|
15
|
-
|
16
6
|
def load(path, options = {})
|
17
7
|
path = path.to_s
|
18
8
|
raise FileNotFound unless File.exist?(path)
|
19
|
-
|
20
|
-
ptr = with_lock do
|
21
|
-
imlib_set_cache_size(0)
|
22
|
-
imlib_load_image_with_error_return(path, load_error.ptr)
|
23
|
-
end
|
24
|
-
raise load_error, load_error.message if ptr.null?
|
25
|
-
return instantiate(ptr)
|
9
|
+
_load(path)
|
26
10
|
end
|
27
11
|
alias :open :load
|
28
12
|
|
29
|
-
protected
|
30
|
-
|
31
|
-
def finalize(ptr)
|
32
|
-
with_lock do
|
33
|
-
imlib_context_set_image(ptr)
|
34
|
-
imlib_free_image
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize(ptr)
|
41
|
-
@handle = Handle.new(self, ptr)
|
42
13
|
end
|
43
|
-
|
44
|
-
def width
|
45
|
-
with_image { imlib_image_get_width }
|
46
|
-
end
|
47
|
-
|
48
|
-
def height
|
49
|
-
with_image { imlib_image_get_height }
|
50
|
-
end
|
51
|
-
|
14
|
+
|
52
15
|
def dimensions
|
53
16
|
[width, height]
|
54
17
|
end
|
55
|
-
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
fmt = format
|
21
|
+
fmt = " #{fmt.upcase}" if fmt
|
22
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)} #{width}x#{height}#{fmt}>"
|
60
23
|
end
|
61
|
-
|
24
|
+
|
62
25
|
def resize(*args)
|
63
|
-
|
26
|
+
_resize(false, *calculate_size(*args))
|
64
27
|
end
|
65
|
-
|
28
|
+
|
66
29
|
def resize!(*args)
|
67
|
-
|
68
|
-
self
|
30
|
+
_resize(true, *calculate_size(*args))
|
69
31
|
end
|
70
|
-
|
71
|
-
def crop(
|
72
|
-
|
32
|
+
|
33
|
+
def crop(x, y, width, height)
|
34
|
+
_crop(false, x, y, width, height)
|
73
35
|
end
|
74
|
-
|
75
|
-
def crop!(
|
76
|
-
|
77
|
-
self
|
36
|
+
|
37
|
+
def crop!(x, y, width, height)
|
38
|
+
_crop(true, x, y, width, height)
|
78
39
|
end
|
79
|
-
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
imlib_image_set_format(format)
|
84
|
-
save_error = SaveError.new
|
85
|
-
imlib_save_image_with_error_return(path, save_error.ptr)
|
86
|
-
raise save_error, save_error.message if save_error.error?
|
87
|
-
true
|
88
|
-
end
|
40
|
+
|
41
|
+
def turn!(orientation)
|
42
|
+
orientation = orientation.abs + 2 if orientation.negative?
|
43
|
+
_turn!(orientation % 4)
|
89
44
|
end
|
90
|
-
|
91
|
-
def
|
92
|
-
|
45
|
+
|
46
|
+
def save(path, format = nil)
|
47
|
+
format ||= format_from_filename(path) || 'jpg'
|
48
|
+
_save(path.to_s, format.to_s)
|
93
49
|
end
|
94
|
-
|
50
|
+
|
95
51
|
private
|
96
52
|
|
97
53
|
# 0.5 0 < scale < 1
|
@@ -102,7 +58,7 @@ module Rszr
|
|
102
58
|
# 400, 300, background: rgba
|
103
59
|
# 400, 300, aspect: false
|
104
60
|
|
105
|
-
def
|
61
|
+
def calculate_size(*args)
|
106
62
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
107
63
|
assert_valid_keys options, :crop, :background, :skew #:extend, :width, :height, :max_width, :max_height, :box
|
108
64
|
original_width, original_height = width, height
|
@@ -142,38 +98,18 @@ module Rszr
|
|
142
98
|
else
|
143
99
|
raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
|
144
100
|
end
|
145
|
-
|
146
|
-
imlib_context_set_anti_alias(1)
|
147
|
-
imlib_create_cropped_scaled_image(x, y, imlib_image_get_width, imlib_image_get_height, new_width.round, new_height.round)
|
148
|
-
end
|
149
|
-
raise TransformationError, "error resizing image" if resized_ptr.null?
|
150
|
-
resized_ptr
|
151
|
-
end
|
152
|
-
|
153
|
-
def create_cropped_image(x, y, width, height)
|
154
|
-
cropped_ptr = with_image { imlib_create_cropped_image(x, y, width, height) }
|
155
|
-
raise TransformationError, 'error cropping image' if cropped_ptr.null?
|
156
|
-
cropped_ptr
|
101
|
+
[x, y, original_width, original_height, new_width.round, new_height.round]
|
157
102
|
end
|
158
103
|
|
159
104
|
def format_from_filename(path)
|
160
105
|
File.extname(path)[1..-1]
|
161
106
|
end
|
162
|
-
|
163
|
-
def
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
def with_image
|
168
|
-
with_lock do
|
169
|
-
context_set_image
|
170
|
-
yield
|
107
|
+
|
108
|
+
def assert_valid_keys(hsh, *valid_keys)
|
109
|
+
if unknown_key = (hsh.keys - valid_keys).first
|
110
|
+
raise ArgumentError.new("Unknown key: #{unknown_key.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
|
171
111
|
end
|
172
112
|
end
|
173
113
|
|
174
|
-
def instantiate(ptr)
|
175
|
-
self.class.send(:instantiate, ptr)
|
176
|
-
end
|
177
|
-
|
178
114
|
end
|
179
115
|
end
|
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.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: byebug
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,23 +122,40 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: memory_profiler
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: Fast image resizer - do one thing and do it fast.
|
112
140
|
email:
|
113
141
|
- mtgrosser@gmx.net
|
114
142
|
executables: []
|
115
|
-
extensions:
|
143
|
+
extensions:
|
144
|
+
- ext/rszr/extconf.rb
|
116
145
|
extra_rdoc_files: []
|
117
146
|
files:
|
118
147
|
- LICENSE
|
119
148
|
- README.md
|
120
149
|
- Rakefile
|
150
|
+
- ext/rszr/errors.c
|
151
|
+
- ext/rszr/errors.h
|
152
|
+
- ext/rszr/extconf.rb
|
153
|
+
- ext/rszr/image.c
|
154
|
+
- ext/rszr/image.h
|
155
|
+
- ext/rszr/rszr.c
|
156
|
+
- ext/rszr/rszr.h
|
121
157
|
- lib/rszr.rb
|
122
|
-
- lib/rszr/base.rb
|
123
|
-
- lib/rszr/errors.rb
|
124
|
-
- lib/rszr/handle.rb
|
125
158
|
- lib/rszr/image.rb
|
126
|
-
- lib/rszr/lib.rb
|
127
|
-
- lib/rszr/lock.rb
|
128
159
|
- lib/rszr/version.rb
|
129
160
|
homepage: https://github.com/mtgrosser/rszr
|
130
161
|
licenses:
|
@@ -134,6 +165,7 @@ post_install_message:
|
|
134
165
|
rdoc_options: []
|
135
166
|
require_paths:
|
136
167
|
- lib
|
168
|
+
- ext
|
137
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
170
|
requirements:
|
139
171
|
- - ">="
|
@@ -145,8 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
177
|
- !ruby/object:Gem::Version
|
146
178
|
version: '0'
|
147
179
|
requirements: []
|
148
|
-
|
149
|
-
rubygems_version: 2.5.2.3
|
180
|
+
rubygems_version: 3.0.1
|
150
181
|
signing_key:
|
151
182
|
specification_version: 4
|
152
183
|
summary: Fast image resizer
|
data/lib/rszr/base.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Rszr
|
2
|
-
module Base
|
3
|
-
|
4
|
-
def self.included(base)
|
5
|
-
Rszr::Lib.delegate(base)
|
6
|
-
Rszr::Lib.delegate(base.singleton_class)
|
7
|
-
base.include(Lock)
|
8
|
-
base.extend(Lock)
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
|
13
|
-
def handle
|
14
|
-
@handle
|
15
|
-
end
|
16
|
-
|
17
|
-
def ptr
|
18
|
-
@handle.ptr
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def assert_valid_keys(hsh, *valid_keys)
|
24
|
-
if unknown_key = (hsh.keys - valid_keys).first
|
25
|
-
raise ArgumentError.new("Unknown key: #{unknown_key.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/rszr/errors.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
module Rszr
|
2
|
-
class Error < StandardError; end
|
3
|
-
|
4
|
-
class ErrorWithMessage < Error
|
5
|
-
MESSAGES = [nil,
|
6
|
-
'File does not exist',
|
7
|
-
'File is a directory',
|
8
|
-
'Read permission denied',
|
9
|
-
'Unsupported format',
|
10
|
-
'Path too long',
|
11
|
-
'Non-existant path component',
|
12
|
-
'Path component is not a directory',
|
13
|
-
'Path outside address space',
|
14
|
-
'Too many symbolic links',
|
15
|
-
'Out of memory',
|
16
|
-
'Out of file descriptors',
|
17
|
-
'Write permission denied',
|
18
|
-
'Out of disk space',
|
19
|
-
'Unknown error']
|
20
|
-
|
21
|
-
attr_reader :ptr
|
22
|
-
|
23
|
-
def initialize
|
24
|
-
@ptr = Fiddle::Pointer.malloc(Rszr::Lib.sizeof('Imlib_Load_Error'))
|
25
|
-
end
|
26
|
-
|
27
|
-
def error?
|
28
|
-
return if ptr.null?
|
29
|
-
0 != ptr[0]
|
30
|
-
end
|
31
|
-
|
32
|
-
def message
|
33
|
-
MESSAGES[ptr[0]] unless ptr.null?
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
class FileNotFound < Error; end
|
39
|
-
class LoadError < ErrorWithMessage; end
|
40
|
-
class TransformationError < Error; end
|
41
|
-
class SaveError < ErrorWithMessage; end
|
42
|
-
end
|
data/lib/rszr/handle.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
module Rszr
|
2
|
-
class Handle
|
3
|
-
attr_reader :ptr, :klass
|
4
|
-
|
5
|
-
def initialize(obj, ptr)
|
6
|
-
@ptr = ptr
|
7
|
-
raise ArgumentError, "#{obj.class.inspect} does not define the finalize class method" unless obj.class.respond_to?(:finalize, true)
|
8
|
-
@klass = obj.class
|
9
|
-
ObjectSpace.define_finalizer(obj, self)
|
10
|
-
end
|
11
|
-
|
12
|
-
def replace!(other_ptr)
|
13
|
-
raise ArgumentError, "Cannot replace pointer with itself" if ptr == other_ptr
|
14
|
-
finalize!
|
15
|
-
@ptr = other_ptr
|
16
|
-
end
|
17
|
-
|
18
|
-
def finalize!(*args)
|
19
|
-
#puts "Finalizing #{args.inspect} #{ptr.inspect}"
|
20
|
-
if !ptr.null? && klass
|
21
|
-
#puts " calling #{args.inspect}"
|
22
|
-
klass.send(:finalize, ptr)
|
23
|
-
@ptr = Fiddle::Pointer.new(0)
|
24
|
-
#else
|
25
|
-
#puts " skipping #{args.inspect}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def release!
|
30
|
-
replace! Fiddle::Pointer.new(0)
|
31
|
-
end
|
32
|
-
|
33
|
-
def call(object_id)
|
34
|
-
finalize!(object_id)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/rszr/lib.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
module Rszr
|
2
|
-
|
3
|
-
module Lib
|
4
|
-
extend Fiddle::Importer
|
5
|
-
|
6
|
-
library, message = case RbConfig::CONFIG['arch']
|
7
|
-
when /darwin/ then ['libImlib2.dylib', 'brew install imlib2']
|
8
|
-
when /mswin/, /cygwin/ then ['imlib2.dll', nil]
|
9
|
-
else
|
10
|
-
['libImlib2.so', "yum install imlib2 imlib2-devel\napt-get install libimlib2 libimlib2-dev"]
|
11
|
-
end
|
12
|
-
|
13
|
-
begin
|
14
|
-
dlload library
|
15
|
-
rescue Fiddle::DLError => e
|
16
|
-
print "\n The Imlib2 library could not be loaded. "
|
17
|
-
puts "You can install it using\n\n #{message}\n" if message
|
18
|
-
puts ''
|
19
|
-
raise e
|
20
|
-
end
|
21
|
-
|
22
|
-
typealias 'Imlib_Image', 'void *'
|
23
|
-
typealias 'Imlib_Context', 'void *'
|
24
|
-
typealias 'enum', 'int'
|
25
|
-
typealias 'Imlib_Load_Error', 'enum'
|
26
|
-
|
27
|
-
#typedef void *Imlib_Color_Modifier;
|
28
|
-
#typedef void *Imlib_Updates;
|
29
|
-
#typedef void *Imlib_Font;
|
30
|
-
#typedef void *Imlib_Color_Range;
|
31
|
-
#typedef void *Imlib_Filter;
|
32
|
-
#typedef struct _imlib_border Imlib_Border;
|
33
|
-
#typedef struct _imlib_color Imlib_Color;
|
34
|
-
#typedef void *ImlibPolygon;
|
35
|
-
|
36
|
-
extern 'int imlib_get_cache_size()'
|
37
|
-
extern 'void imlib_set_cache_size(int)'
|
38
|
-
|
39
|
-
extern 'Imlib_Image imlib_load_image(const char *)'
|
40
|
-
extern 'Imlib_Image imlib_load_image_without_cache(const char *)'
|
41
|
-
extern 'Imlib_Image imlib_load_image_with_error_return(const char *, Imlib_Load_Error *)'
|
42
|
-
extern 'Imlib_Image imlib_create_image(int, int)'
|
43
|
-
extern 'void imlib_context_set_image(Imlib_Image)'
|
44
|
-
extern 'int imlib_image_get_width()'
|
45
|
-
extern 'int imlib_image_get_height()'
|
46
|
-
extern 'void imlib_context_set_anti_alias(char)'
|
47
|
-
|
48
|
-
# source_x, source_y, source_width, source_height, destination_width, destination_height
|
49
|
-
extern 'Imlib_Image imlib_create_cropped_scaled_image(int, int, int, int, int, int)'
|
50
|
-
# x, y, width, height
|
51
|
-
extern 'Imlib_Image imlib_create_cropped_image(int, int, int, int)'
|
52
|
-
|
53
|
-
extern 'char * imlib_image_format()'
|
54
|
-
extern 'void imlib_image_set_format(const char *)'
|
55
|
-
extern 'void imlib_save_image(const char *)'
|
56
|
-
extern 'void imlib_save_image_with_error_return(const char *, Imlib_Load_Error *)'
|
57
|
-
|
58
|
-
extern 'void imlib_free_image()'
|
59
|
-
extern 'void imlib_free_image_and_decache()'
|
60
|
-
|
61
|
-
def self.delegate(base)
|
62
|
-
Lib.methods.grep(/\Aimlib_/).each do |method|
|
63
|
-
line_no = __LINE__; str = %Q{
|
64
|
-
def #{method}(*args, &block)
|
65
|
-
Lib.#{method}(*args, &block)
|
66
|
-
end
|
67
|
-
}
|
68
|
-
base.class_eval(str, __FILE__, line_no)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
data/lib/rszr/lock.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Rszr
|
2
|
-
@mutex = Mutex.new
|
3
|
-
|
4
|
-
class << self
|
5
|
-
|
6
|
-
def with_lock(&block) # :nodoc:
|
7
|
-
mutex.synchronize(&block)
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def mutex
|
13
|
-
@mutex
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
module Lock # :nodoc:
|
18
|
-
def with_lock(&block)
|
19
|
-
Rszr.with_lock(&block)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|