webp-ffi 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -3
- data/CHANGELOG.md +6 -1
- data/README.md +25 -4
- data/ext/webp_ffi/util.c +73 -7
- data/ext/webp_ffi/webp_ffi.c +31 -6
- data/ext/webp_ffi/webp_ffi.h +13 -9
- data/lib/webp/c.rb +20 -1
- data/lib/webp/error.rb +6 -0
- data/lib/webp/options.rb +44 -9
- data/lib/webp/version.rb +1 -1
- data/lib/webp/webp.rb +3 -1
- data/spec/factories/{5.jpg → 3.jpg} +0 -0
- data/spec/factories/3.webp +0 -0
- data/spec/factories/{6.jpg → 4.jpg} +0 -0
- data/spec/factories/4.webp +0 -0
- data/spec/factories/{7.tif → 5.tif} +0 -0
- data/spec/factories/5.webp +0 -0
- data/spec/webp_ffi_spec.rb +69 -30
- metadata +10 -18
- data/spec/factories/3.png +0 -0
- data/spec/factories/4.png +0 -0
- data/spec/factories/6.webp +0 -0
- data/spec/factories/7.webp +0 -0
data/.travis.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
language: ruby
|
2
2
|
before_install:
|
3
|
-
- ./spec/travis_build.sh
|
3
|
+
- ./spec/travis_build.sh > /dev/null 2>&1
|
4
4
|
rvm:
|
5
5
|
- 1.9.2
|
6
6
|
- 1.9.3
|
@@ -18,5 +18,4 @@ branches:
|
|
18
18
|
matrix:
|
19
19
|
allow_failures:
|
20
20
|
- rvm: ruby-head
|
21
|
-
- rvm: jruby-head
|
22
|
-
- rvm: jruby-19mode
|
21
|
+
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
+
## v0.1.4
|
2
|
+
|
3
|
+
* Added decode options
|
4
|
+
* Added error class for decode errors
|
5
|
+
|
1
6
|
## v0.1.3
|
2
7
|
|
3
8
|
* Rename module to WebP
|
4
9
|
|
5
10
|
## v0.1.2
|
6
11
|
|
7
|
-
* Added
|
12
|
+
* Added encode options
|
8
13
|
* Added error class for encode errors
|
9
14
|
|
10
15
|
## v0.1.1
|
data/README.md
CHANGED
@@ -65,7 +65,7 @@ Get size (width and height) from webp image:
|
|
65
65
|
WebP.webp_size(File.open(filename, "rb").read)
|
66
66
|
=> [2000, 2353]
|
67
67
|
|
68
|
-
### Encode
|
68
|
+
### Encode WebP image
|
69
69
|
|
70
70
|
Encode png, jpg or tiff image to webp:
|
71
71
|
|
@@ -73,7 +73,7 @@ Encode png, jpg or tiff image to webp:
|
|
73
73
|
out_filename = File.expand_path(File.join(File.dirname(__FILE__), "tmp/4.webp"))
|
74
74
|
WebP.encode(filename, out_filename)
|
75
75
|
|
76
|
-
Encode png, jpg or tiff image to webp
|
76
|
+
Encode png, jpg or tiff image to webp with options:
|
77
77
|
|
78
78
|
WebP.encode(filename, out_filename, quality: 50, resize_w: 100, resize_h: 200)
|
79
79
|
WebP.encode(filename, out_filename, quality: 75, crop_x: 0, cropt_y: 0, crop_w: 100, crop_h: 100)
|
@@ -103,13 +103,34 @@ Possible encode options:
|
|
103
103
|
* **crop\_x** (int), **crop\_y** (int), **crop\_w** (int), **crop\_h** (int) - crop picture with the given rectangle
|
104
104
|
* **resize\_w** (int), **resize\_h** (int) - resize picture (after any cropping)
|
105
105
|
|
106
|
-
### Decode WebP image
|
106
|
+
### Decode WebP image
|
107
107
|
|
108
|
-
Decode webp image
|
108
|
+
Decode webp image (default format is png):
|
109
109
|
|
110
110
|
filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.webp"))
|
111
111
|
out_filename = File.expand_path(File.join(File.dirname(__FILE__), "tmp/4.png"))
|
112
112
|
WebP.decode(filename, out_filename)
|
113
|
+
|
114
|
+
Decode webp image to pam, ppm or pgm format of image:
|
115
|
+
|
116
|
+
filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.webp"))
|
117
|
+
out_filename = File.expand_path(File.join(File.dirname(__FILE__), "tmp/4.png"))
|
118
|
+
WebP.decode(filename, out_filename, output_format: :pam)
|
119
|
+
WebP.decode(filename, out_filename, output_format: :ppm)
|
120
|
+
WebP.decode(filename, out_filename, output_format: :pgm)
|
121
|
+
|
122
|
+
Decode webp image with options:
|
123
|
+
|
124
|
+
WebP.encode(filename, out_filename, resize_w: 100, resize_h: 200)
|
125
|
+
WebP.encode(filename, out_filename, crop_x: 0, cropt_y: 0, crop_w: 100, crop_h: 100)
|
126
|
+
|
127
|
+
Possible decode options:
|
128
|
+
|
129
|
+
* **bypass\_filtering** (bool) - disable in-loop filtering
|
130
|
+
* **no\_fancy\_upsampling** (bool) - don't use the fancy YUV420 upscaler
|
131
|
+
* **use\_threads** (bool) - use multi-threading
|
132
|
+
* **crop\_x** (int), **crop\_y** (int), **crop\_w** (int), **crop\_h** (int) - crop picture with the given rectangle
|
133
|
+
* **resize\_w** (int), **resize\_h** (int) - resize picture (after any cropping)
|
113
134
|
|
114
135
|
## Contributing
|
115
136
|
|
data/ext/webp_ffi/util.c
CHANGED
@@ -258,6 +258,74 @@ static int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|
258
258
|
return 1;
|
259
259
|
}
|
260
260
|
|
261
|
+
static int UtilWritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
|
262
|
+
const uint32_t width = buffer->width;
|
263
|
+
const uint32_t height = buffer->height;
|
264
|
+
const unsigned char* const rgb = buffer->u.RGBA.rgba;
|
265
|
+
const int stride = buffer->u.RGBA.stride;
|
266
|
+
const size_t bytes_per_px = alpha ? 4 : 3;
|
267
|
+
uint32_t y;
|
268
|
+
|
269
|
+
if (alpha) {
|
270
|
+
fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
|
271
|
+
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
272
|
+
} else {
|
273
|
+
fprintf(fout, "P6\n%d %d\n255\n", width, height);
|
274
|
+
}
|
275
|
+
for (y = 0; y < height; ++y) {
|
276
|
+
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
|
277
|
+
return 0;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
return 1;
|
281
|
+
}
|
282
|
+
|
283
|
+
static int UtilWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
284
|
+
const uint32_t width = buffer->width;
|
285
|
+
const uint32_t height = buffer->height;
|
286
|
+
const unsigned char* const a = buffer->u.YUVA.a;
|
287
|
+
const int a_stride = buffer->u.YUVA.a_stride;
|
288
|
+
uint32_t y;
|
289
|
+
assert(a != NULL);
|
290
|
+
fprintf(fout, "P5\n%d %d\n255\n", width, height);
|
291
|
+
for (y = 0; y < height; ++y) {
|
292
|
+
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
|
293
|
+
return 0;
|
294
|
+
}
|
295
|
+
}
|
296
|
+
return 1;
|
297
|
+
}
|
298
|
+
|
299
|
+
static int UtilWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
|
300
|
+
const int width = buffer->width;
|
301
|
+
const int height = buffer->height;
|
302
|
+
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
|
303
|
+
// Save a grayscale PGM file using the IMC4 layout
|
304
|
+
// (http://www.fourcc.org/yuv.php#IMC4). This is a very
|
305
|
+
// convenient format for viewing the samples, esp. for
|
306
|
+
// odd dimensions.
|
307
|
+
int ok = 1;
|
308
|
+
int y;
|
309
|
+
const int uv_width = (width + 1) / 2;
|
310
|
+
const int uv_height = (height + 1) / 2;
|
311
|
+
const int out_stride = (width + 1) & ~1;
|
312
|
+
const int a_height = yuv->a ? height : 0;
|
313
|
+
fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height + a_height);
|
314
|
+
for (y = 0; ok && y < height; ++y) {
|
315
|
+
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1);
|
316
|
+
if (width & 1) fputc(0, fout); // padding byte
|
317
|
+
}
|
318
|
+
for (y = 0; ok && y < uv_height; ++y) {
|
319
|
+
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
|
320
|
+
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
|
321
|
+
}
|
322
|
+
for (y = 0; ok && y < a_height; ++y) {
|
323
|
+
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1);
|
324
|
+
if (width & 1) fputc(0, fout); // padding byte
|
325
|
+
}
|
326
|
+
return ok;
|
327
|
+
}
|
328
|
+
|
261
329
|
static int UtilReadTIFF(const char* const filename,
|
262
330
|
WebPPicture* const pic, int keep_alpha) {
|
263
331
|
TIFF* const tif = TIFFOpen(filename, "r");
|
@@ -371,18 +439,16 @@ int UtilSaveOutput(const WebPDecBuffer* const buffer,
|
|
371
439
|
|
372
440
|
if (format == PNG) {
|
373
441
|
ok &= UtilWritePNG(fout, buffer);
|
374
|
-
}
|
375
|
-
/*
|
376
442
|
} else if (format == PAM) {
|
377
|
-
ok &=
|
443
|
+
ok &= UtilWritePPM(fout, buffer, 1);
|
378
444
|
} else if (format == PPM) {
|
379
|
-
ok &=
|
445
|
+
ok &= UtilWritePPM(fout, buffer, 0);
|
380
446
|
} else if (format == PGM) {
|
381
|
-
ok &=
|
447
|
+
ok &= UtilWritePGM(fout, buffer);
|
382
448
|
} else if (format == ALPHA_PLANE_ONLY) {
|
383
|
-
ok &=
|
449
|
+
ok &= UtilWriteAlphaPlane(fout, buffer);
|
384
450
|
}
|
385
|
-
|
451
|
+
|
386
452
|
if (fout) {
|
387
453
|
fclose(fout);
|
388
454
|
}
|
data/ext/webp_ffi/webp_ffi.c
CHANGED
@@ -57,7 +57,7 @@ int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeCo
|
|
57
57
|
int keep_alpha = 1;
|
58
58
|
WebPPicture picture;
|
59
59
|
WebPConfig config;
|
60
|
-
//
|
60
|
+
// OPTIONS BEGIN
|
61
61
|
if (encode_config->lossless == 0 || encode_config->lossless == 1){
|
62
62
|
config.lossless = encode_config->lossless;
|
63
63
|
}
|
@@ -115,11 +115,11 @@ int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeCo
|
|
115
115
|
if (encode_config->partition_limit >= 0 && encode_config->partition_limit <= 100){
|
116
116
|
config.partition_limit = encode_config->partition_limit;
|
117
117
|
}
|
118
|
-
|
119
118
|
if ((encode_config->width | encode_config->height) > 0){
|
120
119
|
picture.width = encode_config->width;
|
121
120
|
picture.height = encode_config->height;
|
122
121
|
}
|
122
|
+
// OPTIONS END
|
123
123
|
|
124
124
|
if (!WebPPictureInit(&picture) ||
|
125
125
|
!WebPConfigInit(&config)) {
|
@@ -187,7 +187,7 @@ Error:
|
|
187
187
|
|
188
188
|
|
189
189
|
|
190
|
-
int webp_decode(const char *in_file, const char *out_file) {
|
190
|
+
int webp_decode(const char *in_file, const char *out_file, const FfiWebpDecodeConfig *decode_config) {
|
191
191
|
int return_value = -1;
|
192
192
|
WebPDecoderConfig config;
|
193
193
|
WebPDecBuffer* const output_buffer = &config.output;
|
@@ -195,10 +195,35 @@ int webp_decode(const char *in_file, const char *out_file) {
|
|
195
195
|
OutputFileFormat format = PNG;
|
196
196
|
|
197
197
|
if (!WebPInitDecoderConfig(&config)) {
|
198
|
-
fprintf(stderr, "Library version mismatch!\n");
|
198
|
+
//fprintf(stderr, "Library version mismatch!\n");
|
199
199
|
return 1;
|
200
200
|
}
|
201
201
|
|
202
|
+
if (decode_config->output_format != format){
|
203
|
+
format = decode_config->output_format;
|
204
|
+
}
|
205
|
+
if (decode_config->no_fancy_upsampling > 0){
|
206
|
+
config.options.no_fancy_upsampling = 1;
|
207
|
+
}
|
208
|
+
if (decode_config->bypass_filtering > 0){
|
209
|
+
config.options.bypass_filtering = 1;
|
210
|
+
}
|
211
|
+
if (decode_config->use_threads > 0){
|
212
|
+
config.options.use_threads = 1;
|
213
|
+
}
|
214
|
+
if ((decode_config->crop_w | decode_config->crop_h) > 0){
|
215
|
+
config.options.use_cropping = 1;
|
216
|
+
config.options.crop_left = decode_config->crop_x;
|
217
|
+
config.options.crop_top = decode_config->crop_y;
|
218
|
+
config.options.crop_width = decode_config->crop_w;
|
219
|
+
config.options.crop_height = decode_config->crop_h;
|
220
|
+
}
|
221
|
+
if ((decode_config->resize_w | decode_config->resize_h) > 0){
|
222
|
+
config.options.use_scaling = 1;
|
223
|
+
config.options.scaled_width = decode_config->resize_w;
|
224
|
+
config.options.scaled_height = decode_config->resize_h;
|
225
|
+
}
|
226
|
+
|
202
227
|
VP8StatusCode status = VP8_STATUS_OK;
|
203
228
|
size_t data_size = 0;
|
204
229
|
const uint8_t* data = NULL;
|
@@ -207,7 +232,7 @@ int webp_decode(const char *in_file, const char *out_file) {
|
|
207
232
|
|
208
233
|
status = WebPGetFeatures(data, data_size, bitstream);
|
209
234
|
if (status != VP8_STATUS_OK) {
|
210
|
-
fprintf(stderr, "This is invalid webp image!\n");
|
235
|
+
//fprintf(stderr, "This is invalid webp image!\n");
|
211
236
|
return_value = 2;
|
212
237
|
goto Error;
|
213
238
|
}
|
@@ -235,7 +260,7 @@ int webp_decode(const char *in_file, const char *out_file) {
|
|
235
260
|
status = WebPDecode(data, data_size, &config);
|
236
261
|
|
237
262
|
if (status != VP8_STATUS_OK) {
|
238
|
-
fprintf(stderr, "Decoding of %s failed.\n", in_file);
|
263
|
+
//fprintf(stderr, "Decoding of %s failed.\n", in_file);
|
239
264
|
return_value = 4;
|
240
265
|
goto Error;
|
241
266
|
}
|
data/ext/webp_ffi/webp_ffi.h
CHANGED
@@ -38,22 +38,26 @@ extern "C" {
|
|
38
38
|
int partition_limit; // quality degradation allowed to fit the 512k limit on
|
39
39
|
// prediction modes coding (0: no degradation,
|
40
40
|
// 100: maximum possible degradation).
|
41
|
-
int width;
|
42
|
-
int
|
43
|
-
int
|
44
|
-
int crop_y;
|
45
|
-
int crop_w;
|
46
|
-
int crop_h;
|
47
|
-
int resize_w;
|
48
|
-
int resize_h;
|
41
|
+
int width, height;
|
42
|
+
int crop_x, crop_y, crop_w, crop_h;
|
43
|
+
int resize_w, resize_h;
|
49
44
|
} FfiWebpEncodeConfig;
|
50
45
|
|
46
|
+
typedef struct {
|
47
|
+
OutputFileFormat output_format;
|
48
|
+
int bypass_filtering; // if true, skip the in-loop filtering
|
49
|
+
int no_fancy_upsampling; // if true, use faster pointwise upsampler
|
50
|
+
int crop_x, crop_y, crop_w, crop_h;
|
51
|
+
int resize_w, resize_h;
|
52
|
+
int use_threads; // if true, use multi-threaded decoding
|
53
|
+
} FfiWebpDecodeConfig;
|
54
|
+
|
51
55
|
|
52
56
|
void decoder_version(char *version);
|
53
57
|
void encoder_version(char *version);
|
54
58
|
int webp_get_info(const uint8_t* data, size_t data_size, int* width, int* height);
|
55
59
|
int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeConfig *encode_config);
|
56
|
-
int webp_decode(const char *in_file, const char *out_file);
|
60
|
+
int webp_decode(const char *in_file, const char *out_file, const FfiWebpDecodeConfig *decode_config);
|
57
61
|
int test_c(int n);
|
58
62
|
|
59
63
|
#if defined(__cplusplus) || defined(c_plusplus)
|
data/lib/webp/c.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module WebP
|
2
2
|
module C
|
3
|
+
# enum
|
4
|
+
OutputFileFormat = enum( :png, 0,
|
5
|
+
:pam,
|
6
|
+
:ppm,
|
7
|
+
:pgm,
|
8
|
+
:alpha_plane_only )
|
3
9
|
# struct
|
4
10
|
class FfiWebpEncodeConfig < FFI::Struct
|
5
11
|
layout :lossless, :int,
|
@@ -31,13 +37,26 @@ module WebP
|
|
31
37
|
:resize_w, :int,
|
32
38
|
:resize_h, :int
|
33
39
|
end
|
40
|
+
|
41
|
+
class FfiWebpDecodeConfig < FFI::Struct
|
42
|
+
layout :output_format, OutputFileFormat,
|
43
|
+
:bypass_filtering, :int,
|
44
|
+
:no_fancy_upsampling, :int,
|
45
|
+
:crop_x, :int,
|
46
|
+
:crop_y, :int,
|
47
|
+
:crop_w, :int,
|
48
|
+
:crop_h, :int,
|
49
|
+
:resize_w, :int,
|
50
|
+
:resize_h, :int,
|
51
|
+
:use_threads, :int
|
52
|
+
end
|
34
53
|
|
35
54
|
# webp lib functions
|
36
55
|
attach_function :decoder_version, [:pointer], :void
|
37
56
|
attach_function :encoder_version, [:pointer], :void
|
38
57
|
attach_function :webp_get_info, [:pointer, :size_t, :pointer, :pointer], :int
|
39
58
|
attach_function :webp_encode, [:string, :string, :pointer], :int
|
40
|
-
attach_function :webp_decode, [:string, :string], :int
|
59
|
+
attach_function :webp_decode, [:string, :string, :pointer], :int
|
41
60
|
|
42
61
|
attach_function :test_c, [:int], :int
|
43
62
|
end
|
data/lib/webp/error.rb
CHANGED
@@ -8,6 +8,12 @@ module WebP
|
|
8
8
|
"Cannot crop picture",
|
9
9
|
"Cannot resize picture",
|
10
10
|
"Cannot encode picture as WebP"]
|
11
|
+
|
12
|
+
DECODER_ERRORS = [
|
13
|
+
"Version mismatch",
|
14
|
+
"Invalid webp image",
|
15
|
+
"Invalid output format",
|
16
|
+
"Decoding failed"]
|
11
17
|
|
12
18
|
class InvalidImageFormatError < StandardError; end
|
13
19
|
class EncoderError < StandardError; end
|
data/lib/webp/options.rb
CHANGED
@@ -8,22 +8,57 @@ module WebP
|
|
8
8
|
def encode_pointer
|
9
9
|
options_pointer = FFI::MemoryPointer.new :char, C::FfiWebpEncodeConfig.size, false
|
10
10
|
options_struct = C::FfiWebpEncodeConfig.new options_pointer
|
11
|
-
|
12
|
-
|
13
|
-
options_struct[:crop_x] = options_struct[:crop_y] = 0
|
14
|
-
options_struct[:crop_w] = options_struct[:crop_h] = 0
|
15
|
-
options_struct[:resize_w] = options_struct[:resize_h] = 0
|
16
|
-
# users
|
17
|
-
[:lossless, :quality, :method, :target_size, :target_PSNR,
|
18
|
-
:segments, :sns_strength, :filter_strength, :filter_sharpness,
|
11
|
+
[:lossless, :method, :target_size, :target_PSNR, :segments,
|
12
|
+
:sns_strength, :filter_strength, :filter_sharpness,
|
19
13
|
:filter_type, :autofilter, :alpha_compression, :alpha_filtering,
|
20
14
|
:alpha_quality, :pass, :show_compressed, :preprocessing, :partitions,
|
21
|
-
:partition_limit, :width, :height
|
15
|
+
:partition_limit, :width, :height].each do |key|
|
16
|
+
options_struct[key] = @user_options[key] ? @user_options[key] : -1
|
17
|
+
end
|
18
|
+
encode_default(options_struct)
|
19
|
+
[:quality, :crop_x, :crop_y, :crop_w,
|
20
|
+
:crop_h, :resize_w, :resize_h].each do |key|
|
21
|
+
options_struct[key] = @user_options[key] if @user_options[key]
|
22
|
+
end
|
23
|
+
options_pointer
|
24
|
+
end
|
25
|
+
|
26
|
+
def decode_pointer
|
27
|
+
options_pointer = FFI::MemoryPointer.new :char, C::FfiWebpDecodeConfig.size, false
|
28
|
+
options_struct = C::FfiWebpDecodeConfig.new options_pointer
|
29
|
+
decode_default(options_struct)
|
30
|
+
# options
|
31
|
+
if @user_options[:output_format] && [:png, :pam, :ppm, :pgm, :alpha_plane_only].include?(@user_options[:output_format])
|
32
|
+
options_struct[:output_format] = C::OutputFileFormat[@user_options[:output_format]]
|
33
|
+
end
|
34
|
+
[:bypass_filtering, :no_fancy_upsampling, :use_threads].each do |key|
|
35
|
+
options_struct[key] = 1 if @user_options[key] && true == @user_options[key]
|
36
|
+
end
|
37
|
+
[:crop_x, :crop_y, :crop_w,
|
22
38
|
:crop_h, :resize_w, :resize_h].each do |key|
|
23
39
|
options_struct[key] = @user_options[key] if @user_options[key]
|
24
40
|
end
|
25
41
|
options_pointer
|
26
42
|
end
|
27
43
|
|
44
|
+
private
|
45
|
+
|
46
|
+
def encode_default(options_struct)
|
47
|
+
options_struct[:quality] = 100
|
48
|
+
similar_default(options_struct)
|
49
|
+
end
|
50
|
+
|
51
|
+
def decode_default(options_struct)
|
52
|
+
# default format is png
|
53
|
+
options_struct[:output_format] = C::OutputFileFormat[:png]
|
54
|
+
similar_default(options_struct)
|
55
|
+
end
|
56
|
+
|
57
|
+
def similar_default(options_struct)
|
58
|
+
options_struct[:crop_x] = options_struct[:crop_y] = 0
|
59
|
+
options_struct[:crop_w] = options_struct[:crop_h] = 0
|
60
|
+
options_struct[:resize_w] = options_struct[:resize_h] = 0
|
61
|
+
end
|
62
|
+
|
28
63
|
end
|
29
64
|
end
|
data/lib/webp/version.rb
CHANGED
data/lib/webp/webp.rb
CHANGED
@@ -37,7 +37,9 @@ module WebP
|
|
37
37
|
|
38
38
|
# decode
|
39
39
|
def decode(input_file, output_file, options = {})
|
40
|
-
|
40
|
+
options_obj = Options.new options
|
41
|
+
res = C.webp_decode(input_file, output_file, options_obj.decode_pointer)
|
42
|
+
raise DecoderError, DECODER_ERRORS[res - 1] unless 0 == res
|
41
43
|
return true
|
42
44
|
end
|
43
45
|
|
File without changes
|
data/spec/factories/3.webp
CHANGED
Binary file
|
File without changes
|
data/spec/factories/4.webp
CHANGED
Binary file
|
File without changes
|
data/spec/factories/5.webp
CHANGED
Binary file
|
data/spec/webp_ffi_spec.rb
CHANGED
@@ -2,10 +2,10 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe WebP do
|
4
4
|
factories = {
|
5
|
-
webp: ["1", "2", "3", "4", "5"
|
6
|
-
png: ["1", "2"
|
7
|
-
jpg: ["
|
8
|
-
tiff: ["
|
5
|
+
webp: ["1", "2", "3", "4", "5"],
|
6
|
+
png: ["1", "2"],
|
7
|
+
jpg: ["3", "4"],
|
8
|
+
tiff: ["5"],
|
9
9
|
info: {
|
10
10
|
"1" => {
|
11
11
|
size: [400, 301],
|
@@ -16,22 +16,14 @@ describe WebP do
|
|
16
16
|
has_alpha: true
|
17
17
|
},
|
18
18
|
"3" => {
|
19
|
-
size: [300, 300],
|
20
|
-
has_alpha: true
|
21
|
-
},
|
22
|
-
"4" => {
|
23
|
-
size: [2000, 2353],
|
24
|
-
has_alpha: true
|
25
|
-
},
|
26
|
-
"5" => {
|
27
19
|
size: [550, 368],
|
28
20
|
has_alpha: false
|
29
21
|
},
|
30
|
-
"
|
22
|
+
"4" => {
|
31
23
|
size: [1024, 772],
|
32
24
|
has_alpha: false
|
33
25
|
},
|
34
|
-
"
|
26
|
+
"5" => {
|
35
27
|
size: [1419, 1001],
|
36
28
|
has_alpha: false
|
37
29
|
}
|
@@ -42,6 +34,12 @@ describe WebP do
|
|
42
34
|
@out_dir = File.expand_path(File.join(File.dirname(__FILE__), "../tmp/"))
|
43
35
|
Dir.mkdir(@out_dir) unless File.exists?(@out_dir)
|
44
36
|
end
|
37
|
+
after :all do
|
38
|
+
@out_dir = File.expand_path(File.join(File.dirname(__FILE__), "../tmp/"))
|
39
|
+
#Dir["#{@out_dir}/*{.png,.webp}"].each do |file|
|
40
|
+
# File.delete(file) rescue nil
|
41
|
+
#end
|
42
|
+
end
|
45
43
|
|
46
44
|
it "calculate plus 100 by test_c (verify C)" do
|
47
45
|
WebP::C.test_c(100).should == 200
|
@@ -105,24 +103,22 @@ describe WebP do
|
|
105
103
|
expect { WebP.encode(in_filename, out_filename) }.to raise_error WebP::EncoderError
|
106
104
|
end
|
107
105
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
WebP.encode(in_filename, out_filename, quality: 50)
|
106
|
+
context "with options" do
|
107
|
+
factories[:png].each do |image|
|
108
|
+
it "#{image}.png image" do
|
109
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
110
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.50png.webp"))
|
111
|
+
WebP.encode(in_filename, out_filename, quality: 50, method: 0, alpha_quality: 10, alpha_compression: 1)
|
112
|
+
end
|
116
113
|
end
|
117
114
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
expect { WebP.encode(in_filename, out_filename, crop_w: 30000) }.to raise_error WebP::EncoderError
|
115
|
+
context "raise EncoderError on invalid crop options" do
|
116
|
+
factories[:png].each do |image|
|
117
|
+
it "#{image}.png image" do
|
118
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
119
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.invpng.webp"))
|
120
|
+
expect { WebP.encode(in_filename, out_filename, crop_w: 30000) }.to raise_error WebP::EncoderError
|
121
|
+
end
|
126
122
|
end
|
127
123
|
end
|
128
124
|
end
|
@@ -135,6 +131,49 @@ describe WebP do
|
|
135
131
|
WebP.decode(in_filename, out_filename).should be_true
|
136
132
|
end
|
137
133
|
end
|
134
|
+
context "with output_format" do
|
135
|
+
[:png, :pam, :ppm, :pgm, :alpha_plane_only].each do |output_format|
|
136
|
+
factories[:webp].take(2).each do |image|
|
137
|
+
it "#{image}.webp image to #{output_format}" do
|
138
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.webp"))
|
139
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.#{output_format}.png"))
|
140
|
+
WebP.decode(in_filename, out_filename, output_format: output_format).should be_true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context "with options" do
|
146
|
+
factories[:webp].take(2).each do |image|
|
147
|
+
it "#{image}.webp image to png and crop" do
|
148
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.webp"))
|
149
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}_crop.png"))
|
150
|
+
WebP.decode(in_filename, out_filename, crop_w: 200, crop_h: 200).should be_true
|
151
|
+
end
|
152
|
+
it "#{image}.webp image to png and scale" do
|
153
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.webp"))
|
154
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}_resize.png"))
|
155
|
+
WebP.decode(in_filename, out_filename, resize_w: 200, resize_h: 200).should be_true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
context "raise DecoderError on invalid webp image" do
|
160
|
+
factories[:png].each do |image|
|
161
|
+
it "#{image}.png image" do
|
162
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
163
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.invpng.webp"))
|
164
|
+
expect { WebP.decode(in_filename, out_filename) }.to raise_error WebP::DecoderError
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
context "raise DecoderError on invalid options" do
|
169
|
+
factories[:png].each do |image|
|
170
|
+
it "#{image}.png image" do
|
171
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
172
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.invpng.webp"))
|
173
|
+
expect { WebP.decode(in_filename, out_filename, crop_w: 30000) }.to raise_error WebP::DecoderError
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
138
177
|
end
|
139
178
|
|
140
179
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webp-ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -124,16 +124,12 @@ files:
|
|
124
124
|
- spec/factories/1.webp
|
125
125
|
- spec/factories/2.png
|
126
126
|
- spec/factories/2.webp
|
127
|
-
- spec/factories/3.
|
127
|
+
- spec/factories/3.jpg
|
128
128
|
- spec/factories/3.webp
|
129
|
-
- spec/factories/4.
|
129
|
+
- spec/factories/4.jpg
|
130
130
|
- spec/factories/4.webp
|
131
|
-
- spec/factories/5.
|
131
|
+
- spec/factories/5.tif
|
132
132
|
- spec/factories/5.webp
|
133
|
-
- spec/factories/6.jpg
|
134
|
-
- spec/factories/6.webp
|
135
|
-
- spec/factories/7.tif
|
136
|
-
- spec/factories/7.webp
|
137
133
|
- spec/spec_helper.rb
|
138
134
|
- spec/travis_build.sh
|
139
135
|
- spec/webp_ffi_spec.rb
|
@@ -153,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
149
|
version: '0'
|
154
150
|
segments:
|
155
151
|
- 0
|
156
|
-
hash:
|
152
|
+
hash: -2620577611088835367
|
157
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
154
|
none: false
|
159
155
|
requirements:
|
@@ -162,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
158
|
version: '0'
|
163
159
|
segments:
|
164
160
|
- 0
|
165
|
-
hash:
|
161
|
+
hash: -2620577611088835367
|
166
162
|
requirements: []
|
167
163
|
rubyforge_project:
|
168
164
|
rubygems_version: 1.8.25
|
@@ -174,16 +170,12 @@ test_files:
|
|
174
170
|
- spec/factories/1.webp
|
175
171
|
- spec/factories/2.png
|
176
172
|
- spec/factories/2.webp
|
177
|
-
- spec/factories/3.
|
173
|
+
- spec/factories/3.jpg
|
178
174
|
- spec/factories/3.webp
|
179
|
-
- spec/factories/4.
|
175
|
+
- spec/factories/4.jpg
|
180
176
|
- spec/factories/4.webp
|
181
|
-
- spec/factories/5.
|
177
|
+
- spec/factories/5.tif
|
182
178
|
- spec/factories/5.webp
|
183
|
-
- spec/factories/6.jpg
|
184
|
-
- spec/factories/6.webp
|
185
|
-
- spec/factories/7.tif
|
186
|
-
- spec/factories/7.webp
|
187
179
|
- spec/spec_helper.rb
|
188
180
|
- spec/travis_build.sh
|
189
181
|
- spec/webp_ffi_spec.rb
|
data/spec/factories/3.png
DELETED
Binary file
|
data/spec/factories/4.png
DELETED
Binary file
|
data/spec/factories/6.webp
DELETED
Binary file
|
data/spec/factories/7.webp
DELETED
Binary file
|