webp-ffi 0.1.3 → 0.1.4
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.
- 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
|