rszr 0.4.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|