webp-ffi 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +24 -25
- data/Rakefile +1 -0
- data/ext/webp_ffi/Rakefile +1 -0
- data/ext/webp_ffi/util.c +139 -11
- data/ext/webp_ffi/util.h +1 -1
- data/ext/webp_ffi/webp_ffi.c +48 -4
- data/ext/webp_ffi/webp_ffi.h +16 -3
- data/lib/webp_ffi.rb +2 -1
- data/lib/webp_ffi/c.rb +18 -11
- data/lib/webp_ffi/options.rb +26 -0
- data/lib/webp_ffi/version.rb +1 -1
- data/lib/webp_ffi/webp_ffi.rb +3 -1
- data/spec/factories/7.tif +0 -0
- data/spec/factories/7.webp +0 -0
- data/spec/webp_ffi_spec.rb +41 -6
- metadata +8 -5
- data/spec/bindings.md +0 -19
data/README.md
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
[](https://travis-ci.org/le0pard/webp-ffi)
|
4
4
|
[](https://codeclimate.com/github/le0pard/webp-ffi)
|
5
5
|
|
6
|
-
Ruby wrapper for libwebp.
|
6
|
+
Ruby wrapper for libwebp. What is WebP?
|
7
|
+
|
8
|
+
WebP is a new image format that provides lossless and lossy compression for images on the web. WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller in size compared to JPEG images at equivalent SSIM index. WebP supports lossless transparency (also known as alpha channel) with just 22% additional bytes. Transparency is also supported with lossy compression and typically provides 3x smaller file sizes compared to PNG when lossy compression is acceptable for the red/green/blue color channels.
|
9
|
+
|
10
|
+
## [WebP Gallery](https://developers.google.com/speed/webp/gallery)
|
7
11
|
|
8
12
|
## Installation
|
9
13
|
|
@@ -13,16 +17,15 @@ First of all you should have install libraries: libpng, libjpeg and libwebp (for
|
|
13
17
|
|
14
18
|
For ubuntu, debian:
|
15
19
|
|
16
|
-
sudo apt-get install libjpeg62-dev
|
17
|
-
sudo apt-get install libpng12-dev
|
20
|
+
sudo apt-get install libjpeg62-dev libpng12-dev libtiff4-dev
|
18
21
|
|
19
22
|
For Mac OS:
|
20
23
|
|
21
|
-
sudo port install jpeg libpng
|
24
|
+
sudo port install jpeg libpng tiff
|
22
25
|
|
23
26
|
or:
|
24
27
|
|
25
|
-
brew install libjpg libpng
|
28
|
+
brew install libjpg libpng libtiff
|
26
29
|
|
27
30
|
Next, you should [install libwebp](https://developers.google.com/speed/webp/docs/compiling).
|
28
31
|
|
@@ -54,30 +57,26 @@ Basic info about libwebp (encoder and decoder versions):
|
|
54
57
|
|
55
58
|
Get size (width and height) from webp image:
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
2.0.0p0 :006 > filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.webp"))
|
60
|
-
2.0.0p0 :007 > WebpFfi.webp_size(data = File.open(filename, "rb").read)
|
60
|
+
filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.webp"))
|
61
|
+
WebpFfi.webp_size(File.open(filename, "rb").read)
|
61
62
|
=> [2000, 2353]
|
62
63
|
|
63
64
|
Decode webp image to png:
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
2.0.0p0 :013 > WebpFfi.encode(filename, out_filename)
|
80
|
-
=> 0
|
66
|
+
filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.webp"))
|
67
|
+
out_filename = File.expand_path(File.join(File.dirname(__FILE__), "tmp/4.png"))
|
68
|
+
WebpFfi.decode(filename, out_filename)
|
69
|
+
|
70
|
+
Encode png, jpg or tiff image to webp:
|
71
|
+
|
72
|
+
filename = File.expand_path(File.join(File.dirname(__FILE__), "spec/factories/4.png"))
|
73
|
+
out_filename = File.expand_path(File.join(File.dirname(__FILE__), "tmp/4.webp"))
|
74
|
+
WebpFfi.encode(filename, out_filename)
|
75
|
+
|
76
|
+
Encode png, jpg or tiff image to webp (with options):
|
77
|
+
|
78
|
+
WebpFfi.encode(filename, out_filename, quality: 50, resize_w: 100, resize_h: 200)
|
79
|
+
WebpFfi.encode(filename, out_filename, quality: 75, crop_x: 0, cropt_y: 0, crop_w: 100, crop_h: 100)
|
81
80
|
|
82
81
|
## Contributing
|
83
82
|
|
data/Rakefile
CHANGED
data/ext/webp_ffi/Rakefile
CHANGED
data/ext/webp_ffi/util.c
CHANGED
@@ -9,6 +9,8 @@
|
|
9
9
|
#include <setjmp.h> // note: this must be included *after* png.h
|
10
10
|
#include <jpeglib.h>
|
11
11
|
|
12
|
+
#include <tiffio.h>
|
13
|
+
|
12
14
|
#include "webp/decode.h"
|
13
15
|
#include "webp/encode.h"
|
14
16
|
|
@@ -46,6 +48,88 @@ static int UtilReadYUV(FILE* in_file, WebPPicture* const pic) {
|
|
46
48
|
return ok;
|
47
49
|
}
|
48
50
|
|
51
|
+
struct my_error_mgr {
|
52
|
+
struct jpeg_error_mgr pub;
|
53
|
+
jmp_buf setjmp_buffer;
|
54
|
+
};
|
55
|
+
|
56
|
+
static void my_error_exit(j_common_ptr dinfo) {
|
57
|
+
struct my_error_mgr* myerr = (struct my_error_mgr*) dinfo->err;
|
58
|
+
(*dinfo->err->output_message) (dinfo);
|
59
|
+
longjmp(myerr->setjmp_buffer, 1);
|
60
|
+
}
|
61
|
+
|
62
|
+
static int UtilReadJPEG(FILE* in_file, WebPPicture* const pic) {
|
63
|
+
int ok = 0;
|
64
|
+
int stride, width, height;
|
65
|
+
uint8_t* rgb = NULL;
|
66
|
+
uint8_t* row_ptr = NULL;
|
67
|
+
struct jpeg_decompress_struct dinfo;
|
68
|
+
struct my_error_mgr jerr;
|
69
|
+
JSAMPARRAY buffer;
|
70
|
+
|
71
|
+
dinfo.err = jpeg_std_error(&jerr.pub);
|
72
|
+
jerr.pub.error_exit = my_error_exit;
|
73
|
+
|
74
|
+
if (setjmp(jerr.setjmp_buffer)) {
|
75
|
+
Error:
|
76
|
+
jpeg_destroy_decompress(&dinfo);
|
77
|
+
goto End;
|
78
|
+
}
|
79
|
+
|
80
|
+
jpeg_create_decompress(&dinfo);
|
81
|
+
jpeg_stdio_src(&dinfo, in_file);
|
82
|
+
jpeg_read_header(&dinfo, TRUE);
|
83
|
+
|
84
|
+
dinfo.out_color_space = JCS_RGB;
|
85
|
+
dinfo.dct_method = JDCT_IFAST;
|
86
|
+
dinfo.do_fancy_upsampling = TRUE;
|
87
|
+
|
88
|
+
jpeg_start_decompress(&dinfo);
|
89
|
+
|
90
|
+
if (dinfo.output_components != 3) {
|
91
|
+
goto Error;
|
92
|
+
}
|
93
|
+
|
94
|
+
width = dinfo.output_width;
|
95
|
+
height = dinfo.output_height;
|
96
|
+
stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);
|
97
|
+
|
98
|
+
rgb = (uint8_t*)malloc(stride * height);
|
99
|
+
if (rgb == NULL) {
|
100
|
+
goto End;
|
101
|
+
}
|
102
|
+
row_ptr = rgb;
|
103
|
+
|
104
|
+
buffer = (*dinfo.mem->alloc_sarray) ((j_common_ptr) &dinfo,
|
105
|
+
JPOOL_IMAGE, stride, 1);
|
106
|
+
if (buffer == NULL) {
|
107
|
+
goto End;
|
108
|
+
}
|
109
|
+
|
110
|
+
while (dinfo.output_scanline < dinfo.output_height) {
|
111
|
+
if (jpeg_read_scanlines(&dinfo, buffer, 1) != 1) {
|
112
|
+
goto End;
|
113
|
+
}
|
114
|
+
memcpy(row_ptr, buffer[0], stride);
|
115
|
+
row_ptr += stride;
|
116
|
+
}
|
117
|
+
|
118
|
+
jpeg_finish_decompress(&dinfo);
|
119
|
+
jpeg_destroy_decompress(&dinfo);
|
120
|
+
|
121
|
+
// WebP conversion.
|
122
|
+
pic->width = width;
|
123
|
+
pic->height = height;
|
124
|
+
ok = WebPPictureImportRGB(pic, rgb, stride);
|
125
|
+
|
126
|
+
End:
|
127
|
+
if (rgb) {
|
128
|
+
free(rgb);
|
129
|
+
}
|
130
|
+
return ok;
|
131
|
+
}
|
132
|
+
|
49
133
|
static void PNGAPI error_function(png_structp png, png_const_charp dummy) {
|
50
134
|
(void)dummy; // remove variable-unused warning
|
51
135
|
longjmp(png_jmpbuf(png), 1);
|
@@ -174,6 +258,57 @@ static int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|
174
258
|
return 1;
|
175
259
|
}
|
176
260
|
|
261
|
+
static int UtilReadTIFF(const char* const filename,
|
262
|
+
WebPPicture* const pic, int keep_alpha) {
|
263
|
+
TIFF* const tif = TIFFOpen(filename, "r");
|
264
|
+
uint32 width, height;
|
265
|
+
uint32* raster;
|
266
|
+
int ok = 0;
|
267
|
+
int dircount = 1;
|
268
|
+
|
269
|
+
if (tif == NULL) {
|
270
|
+
fprintf(stderr, "Error! Cannot open TIFF file '%s'\n", filename);
|
271
|
+
return 0;
|
272
|
+
}
|
273
|
+
|
274
|
+
while (TIFFReadDirectory(tif)) ++dircount;
|
275
|
+
|
276
|
+
if (dircount > 1) {
|
277
|
+
fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n"
|
278
|
+
"Only the first will be used, %d will be ignored.\n",
|
279
|
+
dircount - 1);
|
280
|
+
}
|
281
|
+
|
282
|
+
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
|
283
|
+
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
|
284
|
+
raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster));
|
285
|
+
if (raster != NULL) {
|
286
|
+
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
|
287
|
+
ORIENTATION_TOPLEFT, 1)) {
|
288
|
+
const int stride = width * sizeof(*raster);
|
289
|
+
pic->width = width;
|
290
|
+
pic->height = height;
|
291
|
+
// TIFF data is ABGR
|
292
|
+
#ifdef __BIG_ENDIAN__
|
293
|
+
TIFFSwabArrayOfLong(raster, width * height);
|
294
|
+
#endif
|
295
|
+
ok = keep_alpha
|
296
|
+
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
|
297
|
+
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
|
298
|
+
}
|
299
|
+
_TIFFfree(raster);
|
300
|
+
} else {
|
301
|
+
fprintf(stderr, "Error allocating TIFF RGBA memory!\n");
|
302
|
+
}
|
303
|
+
|
304
|
+
if (ok && keep_alpha == 2) {
|
305
|
+
WebPCleanupTransparentArea(pic);
|
306
|
+
}
|
307
|
+
|
308
|
+
TIFFClose(tif);
|
309
|
+
return ok;
|
310
|
+
}
|
311
|
+
|
177
312
|
static InputFileFormat GetImageType(FILE* in_file) {
|
178
313
|
InputFileFormat format = UNSUPPORTED;
|
179
314
|
unsigned int magic;
|
@@ -209,14 +344,11 @@ int UtilReadPicture(const char* const filename, WebPPicture* const pic,
|
|
209
344
|
const InputFileFormat format = GetImageType(in_file);
|
210
345
|
if (format == PNG_) {
|
211
346
|
ok = UtilReadPNG(in_file, pic, keep_alpha);
|
212
|
-
}
|
213
|
-
/*
|
214
347
|
} else if (format == JPEG_) {
|
215
|
-
ok =
|
348
|
+
ok = UtilReadJPEG(in_file, pic);
|
216
349
|
} else if (format == TIFF_) {
|
217
|
-
ok =
|
350
|
+
ok = UtilReadTIFF(filename, pic, keep_alpha);
|
218
351
|
}
|
219
|
-
*/
|
220
352
|
} else {
|
221
353
|
// If image size is specified, infer it as YUV format.
|
222
354
|
ok = UtilReadYUV(in_file, pic);
|
@@ -229,7 +361,7 @@ int UtilReadPicture(const char* const filename, WebPPicture* const pic,
|
|
229
361
|
return ok;
|
230
362
|
}
|
231
363
|
|
232
|
-
|
364
|
+
int UtilSaveOutput(const WebPDecBuffer* const buffer,
|
233
365
|
OutputFileFormat format, const char* const out_file) {
|
234
366
|
FILE* fout = NULL;
|
235
367
|
int ok = 1;
|
@@ -257,11 +389,7 @@ void UtilSaveOutput(const WebPDecBuffer* const buffer,
|
|
257
389
|
if (fout) {
|
258
390
|
fclose(fout);
|
259
391
|
}
|
260
|
-
|
261
|
-
printf("Saved file %s\n", out_file);
|
262
|
-
} else {
|
263
|
-
fprintf(stderr, "Error writing file %s !!\n", out_file);
|
264
|
-
}
|
392
|
+
return ok;
|
265
393
|
}
|
266
394
|
|
267
395
|
// -----------------------------------------------------------------------------
|
data/ext/webp_ffi/util.h
CHANGED
@@ -20,7 +20,7 @@ typedef enum {
|
|
20
20
|
UNSUPPORTED
|
21
21
|
} InputFileFormat;
|
22
22
|
|
23
|
-
|
23
|
+
int UtilSaveOutput(const WebPDecBuffer* const buffer, OutputFileFormat format, const char* const out_file);
|
24
24
|
// Allocates storage for entire file 'file_name' and returns contents and size
|
25
25
|
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
|
26
26
|
// be deleted using free().
|
data/ext/webp_ffi/webp_ffi.c
CHANGED
@@ -114,13 +114,41 @@ Error:
|
|
114
114
|
|
115
115
|
|
116
116
|
|
117
|
-
int webp_encode(const char *in_file, const char *out_file) {
|
117
|
+
int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeConfig *encode_config) {
|
118
118
|
int return_value = -1;
|
119
119
|
FILE *out = NULL;
|
120
120
|
int keep_alpha = 1;
|
121
121
|
WebPPicture picture;
|
122
122
|
WebPConfig config;
|
123
|
-
|
123
|
+
// config
|
124
|
+
if (encode_config->lossless && (encode_config->lossless == 0 || encode_config->lossless == 1)){
|
125
|
+
config.lossless = encode_config->lossless;
|
126
|
+
}
|
127
|
+
if (encode_config->quality){
|
128
|
+
config.quality = encode_config->quality;
|
129
|
+
}
|
130
|
+
if (encode_config->method >= 0 && encode_config->method <= 6){
|
131
|
+
config.method = encode_config->method;
|
132
|
+
}
|
133
|
+
if (encode_config->segments){
|
134
|
+
config.segments = encode_config->segments;
|
135
|
+
}
|
136
|
+
if (encode_config->sns_strength){
|
137
|
+
config.sns_strength = encode_config->sns_strength;
|
138
|
+
}
|
139
|
+
if (encode_config->alpha_quality){
|
140
|
+
config.alpha_quality = encode_config->alpha_quality;
|
141
|
+
}
|
142
|
+
if (encode_config->alpha_compression){
|
143
|
+
config.alpha_compression = encode_config->alpha_compression;
|
144
|
+
}
|
145
|
+
if (encode_config->alpha_filtering){
|
146
|
+
config.alpha_filtering = encode_config->alpha_filtering;
|
147
|
+
}
|
148
|
+
if (encode_config->width && encode_config->height){
|
149
|
+
picture.width = encode_config->width;
|
150
|
+
picture.height = encode_config->height;
|
151
|
+
}
|
124
152
|
|
125
153
|
if (!WebPPictureInit(&picture) ||
|
126
154
|
!WebPConfigInit(&config)) {
|
@@ -149,13 +177,29 @@ int webp_encode(const char *in_file, const char *out_file) {
|
|
149
177
|
picture.writer = EncodeWriter;
|
150
178
|
picture.custom_ptr = (void*)out;
|
151
179
|
|
180
|
+
if ((encode_config->crop_w | encode_config->crop_h) > 0){
|
181
|
+
if (!WebPPictureView(&picture, encode_config->crop_x, encode_config->crop_y, encode_config->crop_w, encode_config->crop_h, &picture)) {
|
182
|
+
fprintf(stderr, "Error! Cannot crop picture\n");
|
183
|
+
return_value = 5;
|
184
|
+
goto Error;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
if ((encode_config->resize_w | encode_config->resize_h) > 0) {
|
189
|
+
if (!WebPPictureRescale(&picture, encode_config->resize_w, encode_config->resize_h)) {
|
190
|
+
fprintf(stderr, "Error! Cannot resize picture\n");
|
191
|
+
return_value = 6;
|
192
|
+
goto Error;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
152
196
|
if (picture.extra_info_type > 0) {
|
153
197
|
AllocExtraInfo(&picture);
|
154
198
|
}
|
155
199
|
|
156
200
|
if (!WebPEncode(&config, &picture)) {
|
157
201
|
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
|
158
|
-
return_value =
|
202
|
+
return_value = 10;
|
159
203
|
goto Error;
|
160
204
|
}
|
161
205
|
return_value = 0;
|
@@ -171,7 +215,7 @@ Error:
|
|
171
215
|
}
|
172
216
|
|
173
217
|
// test
|
174
|
-
int
|
218
|
+
int test_c(int n) {
|
175
219
|
return n + 100;
|
176
220
|
}
|
177
221
|
|
data/ext/webp_ffi/webp_ffi.h
CHANGED
@@ -9,14 +9,27 @@ extern "C" {
|
|
9
9
|
int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
|
10
10
|
float quality; // between 0 (smallest file) and 100 (biggest)
|
11
11
|
int method; // quality/speed trade-off (0=fast, 6=slower-better)
|
12
|
-
|
12
|
+
int segments; // maximum number of segments to use, in [1..4]
|
13
|
+
int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum.
|
14
|
+
int alpha_quality; // Between 0 (smallest size) and 100 (lossless). Default is 100.
|
15
|
+
int alpha_compression; // Algorithm for encoding the alpha plane
|
16
|
+
int alpha_filtering; // Predictive filtering method for alpha plane.
|
17
|
+
int width;
|
18
|
+
int height;
|
19
|
+
int crop_x;
|
20
|
+
int crop_y;
|
21
|
+
int crop_w;
|
22
|
+
int crop_h;
|
23
|
+
int resize_w;
|
24
|
+
int resize_h;
|
25
|
+
} FfiWebpEncodeConfig;
|
13
26
|
|
14
27
|
void decoder_version(char *version);
|
15
28
|
void encoder_version(char *version);
|
16
29
|
int webp_get_info(const uint8_t* data, size_t data_size, int* width, int* height);
|
17
30
|
int webp_decode(const char *in_file, const char *out_file);
|
18
|
-
int webp_encode(const char *in_file, const char *out_file);
|
19
|
-
int
|
31
|
+
int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeConfig *encode_config);
|
32
|
+
int test_c(int n);
|
20
33
|
|
21
34
|
#if defined(__cplusplus) || defined(c_plusplus)
|
22
35
|
} // extern "C"
|
data/lib/webp_ffi.rb
CHANGED
data/lib/webp_ffi/c.rb
CHANGED
@@ -1,25 +1,32 @@
|
|
1
1
|
module WebpFfi
|
2
2
|
module C
|
3
|
-
# enum
|
4
|
-
WebpImageHint = enum(:webp_hint_default, 0,
|
5
|
-
:webp_hint_picture,
|
6
|
-
:webp_hint_photo,
|
7
|
-
:webp_hint_graph,
|
8
|
-
:webp_hint_last)
|
9
3
|
# struct
|
10
|
-
class
|
4
|
+
class FfiWebpEncodeConfig < FFI::Struct
|
11
5
|
layout :lossless, :int,
|
12
6
|
:quality, :float,
|
13
|
-
:method, :int
|
7
|
+
:method, :int,
|
8
|
+
:segments, :int,
|
9
|
+
:sns_strength, :int,
|
10
|
+
:alpha_quality, :int,
|
11
|
+
:alpha_compression, :int,
|
12
|
+
:alpha_filtering, :int,
|
13
|
+
:width, :int,
|
14
|
+
:height, :int,
|
15
|
+
:crop_x, :int,
|
16
|
+
:crop_y, :int,
|
17
|
+
:crop_w, :int,
|
18
|
+
:crop_h, :int,
|
19
|
+
:resize_w, :int,
|
20
|
+
:resize_h, :int
|
14
21
|
end
|
15
|
-
|
22
|
+
|
16
23
|
# webp lib functions
|
17
24
|
attach_function :decoder_version, [:pointer], :void
|
18
25
|
attach_function :encoder_version, [:pointer], :void
|
19
26
|
attach_function :webp_get_info, [:pointer, :size_t, :pointer, :pointer], :int
|
20
27
|
attach_function :webp_decode, [:string, :string], :int
|
21
|
-
attach_function :webp_encode, [:string, :string], :int
|
28
|
+
attach_function :webp_encode, [:string, :string, :pointer], :int
|
22
29
|
|
23
|
-
attach_function :
|
30
|
+
attach_function :test_c, [:int], :int
|
24
31
|
end
|
25
32
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module WebpFfi
|
2
|
+
class Options
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@user_options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def encode_pointer
|
9
|
+
options_pointer = FFI::MemoryPointer.new :char, C::FfiWebpEncodeConfig.size, false
|
10
|
+
options_struct = C::FfiWebpEncodeConfig.new options_pointer
|
11
|
+
# default
|
12
|
+
options_struct[:quality] = 100
|
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, :segments, :sns_strength,
|
18
|
+
:alpha_quality, :alpha_compression, :alpha_filtering, :width, :height,
|
19
|
+
:crop_x, :crop_y, :crop_w, :crop_h, :resize_w, :resize_h].each do |key|
|
20
|
+
options_struct[key] = @user_options[key] if @user_options[key]
|
21
|
+
end
|
22
|
+
options_pointer
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/webp_ffi/version.rb
CHANGED
data/lib/webp_ffi/webp_ffi.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "webp_ffi/options"
|
1
2
|
require "webp_ffi/c"
|
2
3
|
|
3
4
|
module WebpFfi
|
@@ -38,7 +39,8 @@ module WebpFfi
|
|
38
39
|
|
39
40
|
# encode
|
40
41
|
def encode(input_file, output_file, options = {})
|
41
|
-
|
42
|
+
options_obj = Options.new options
|
43
|
+
C.webp_encode(input_file, output_file, options_obj.encode_pointer)
|
42
44
|
end
|
43
45
|
|
44
46
|
end
|
Binary file
|
Binary file
|
data/spec/webp_ffi_spec.rb
CHANGED
@@ -2,9 +2,10 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe WebpFfi do
|
4
4
|
factories = {
|
5
|
-
webp: ["1", "2", "3", "4", "5", "6"],
|
5
|
+
webp: ["1", "2", "3", "4", "5", "6", "7"],
|
6
6
|
png: ["1", "2", "3", "4"],
|
7
7
|
jpg: ["5", "6"],
|
8
|
+
tiff: ["7"],
|
8
9
|
info: {
|
9
10
|
"1" => {
|
10
11
|
size: [400, 301],
|
@@ -29,13 +30,17 @@ describe WebpFfi do
|
|
29
30
|
"6" => {
|
30
31
|
size: [1024, 772],
|
31
32
|
has_alpha: false
|
33
|
+
},
|
34
|
+
"7" => {
|
35
|
+
size: [1419, 1001],
|
36
|
+
has_alpha: false
|
32
37
|
}
|
33
38
|
}
|
34
39
|
}
|
35
40
|
|
36
41
|
it "calculate plus 100 by test" do
|
37
|
-
WebpFfi::C.
|
38
|
-
WebpFfi::C.
|
42
|
+
WebpFfi::C.test_c(100).should == 200
|
43
|
+
WebpFfi::C.test_c(150).should == 250
|
39
44
|
end
|
40
45
|
|
41
46
|
it "decoder version" do
|
@@ -79,15 +84,45 @@ describe WebpFfi do
|
|
79
84
|
end
|
80
85
|
|
81
86
|
context "encode" do
|
87
|
+
before :all do
|
88
|
+
@out_dir = File.expand_path(File.join(File.dirname(__FILE__), "../tmp/"))
|
89
|
+
Dir.mkdir(@out_dir) unless File.exists?(@out_dir)
|
90
|
+
end
|
82
91
|
factories[:png].each do |image|
|
83
92
|
it "#{image}.png image" do
|
84
|
-
out_dir = File.expand_path(File.join(File.dirname(__FILE__), "../tmp/"))
|
85
|
-
Dir.mkdir(out_dir) unless File.exists?(out_dir)
|
86
93
|
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
87
|
-
out_filename = File.expand_path(File.join(out_dir, "#{image}.png.webp"))
|
94
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.png.webp"))
|
88
95
|
WebpFfi.encode(in_filename, out_filename)
|
89
96
|
end
|
90
97
|
end
|
98
|
+
factories[:jpg].each do |image|
|
99
|
+
it "#{image}.jpg image" do
|
100
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.jpg"))
|
101
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.jpg.webp"))
|
102
|
+
WebpFfi.encode(in_filename, out_filename)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
factories[:tiff].each do |image|
|
106
|
+
it "#{image}.tif image" do
|
107
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.tif"))
|
108
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.tif.webp"))
|
109
|
+
WebpFfi.encode(in_filename, out_filename)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "encode with options" do
|
115
|
+
before :all do
|
116
|
+
@out_dir = File.expand_path(File.join(File.dirname(__FILE__), "../tmp/"))
|
117
|
+
Dir.mkdir(@out_dir) unless File.exists?(@out_dir)
|
118
|
+
end
|
119
|
+
factories[:png].each do |image|
|
120
|
+
it "#{image}.png image" do
|
121
|
+
in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.png"))
|
122
|
+
out_filename = File.expand_path(File.join(@out_dir, "#{image}.50png.webp"))
|
123
|
+
WebpFfi.encode(in_filename, out_filename, quality: 50)
|
124
|
+
end
|
125
|
+
end
|
91
126
|
end
|
92
127
|
|
93
128
|
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.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -100,9 +100,9 @@ files:
|
|
100
100
|
- lib/webp_ffi/c.rb
|
101
101
|
- lib/webp_ffi/error.rb
|
102
102
|
- lib/webp_ffi/libc.rb
|
103
|
+
- lib/webp_ffi/options.rb
|
103
104
|
- lib/webp_ffi/version.rb
|
104
105
|
- lib/webp_ffi/webp_ffi.rb
|
105
|
-
- spec/bindings.md
|
106
106
|
- spec/factories/1.png
|
107
107
|
- spec/factories/1.webp
|
108
108
|
- spec/factories/2.png
|
@@ -115,6 +115,8 @@ files:
|
|
115
115
|
- spec/factories/5.webp
|
116
116
|
- spec/factories/6.jpg
|
117
117
|
- spec/factories/6.webp
|
118
|
+
- spec/factories/7.tif
|
119
|
+
- spec/factories/7.webp
|
118
120
|
- spec/spec_helper.rb
|
119
121
|
- spec/travis_build.sh
|
120
122
|
- spec/webp_ffi_spec.rb
|
@@ -134,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
136
|
version: '0'
|
135
137
|
segments:
|
136
138
|
- 0
|
137
|
-
hash: -
|
139
|
+
hash: -4057552574747180548
|
138
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
141
|
none: false
|
140
142
|
requirements:
|
@@ -143,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
145
|
version: '0'
|
144
146
|
segments:
|
145
147
|
- 0
|
146
|
-
hash: -
|
148
|
+
hash: -4057552574747180548
|
147
149
|
requirements: []
|
148
150
|
rubyforge_project:
|
149
151
|
rubygems_version: 1.8.25
|
@@ -151,7 +153,6 @@ signing_key:
|
|
151
153
|
specification_version: 3
|
152
154
|
summary: Ruby wrapper for libwebp
|
153
155
|
test_files:
|
154
|
-
- spec/bindings.md
|
155
156
|
- spec/factories/1.png
|
156
157
|
- spec/factories/1.webp
|
157
158
|
- spec/factories/2.png
|
@@ -164,6 +165,8 @@ test_files:
|
|
164
165
|
- spec/factories/5.webp
|
165
166
|
- spec/factories/6.jpg
|
166
167
|
- spec/factories/6.webp
|
168
|
+
- spec/factories/7.tif
|
169
|
+
- spec/factories/7.webp
|
167
170
|
- spec/spec_helper.rb
|
168
171
|
- spec/travis_build.sh
|
169
172
|
- spec/webp_ffi_spec.rb
|
data/spec/bindings.md
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Decode:
|
2
|
-
WebPGetDecoderVersion
|
3
|
-
WebPGetInfo
|
4
|
-
WebPDecodeRGBA
|
5
|
-
WebPDecodeARGB
|
6
|
-
WebPDecodeBGRA
|
7
|
-
WebPDecodeBGR
|
8
|
-
WebPDecodeRGB
|
9
|
-
|
10
|
-
Encode:
|
11
|
-
WebPGetEncoderVersion
|
12
|
-
WebPEncodeRGBA
|
13
|
-
WebPEncodeBGRA
|
14
|
-
WebPEncodeRGB
|
15
|
-
WebPEncodeBGR
|
16
|
-
WebPEncodeLosslessRGBA
|
17
|
-
WebPEncodeLosslessBGRA
|
18
|
-
WebPEncodeLosslessRGB
|
19
|
-
WebPEncodeLosslessBGR
|