webp-ffi 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5dc135cb052630588802ca113f8d11a18ccd0dfe
4
- data.tar.gz: 685b69ef56c9d2928ab5a6c2f1631f5675bb5796
2
+ SHA256:
3
+ metadata.gz: 2cf844bf54ff536c29ad8b940b311add0e2dfc9bdf1279f09da6346d0ef14648
4
+ data.tar.gz: 4c04e7ebcd080732f008e7a03468d7ac83ff856af311854b04bacd5b370c8b1d
5
5
  SHA512:
6
- metadata.gz: 4b38a77daf24a59aebe807b2444f2a8c601392f78d1d4bdac3363887268ecd2f647577c66bad6847b9dd4ebc147d53c81b5724da042107b4ec1712a427a39edc
7
- data.tar.gz: 56a5f00d3cc2b4719060d5e6b03684754d34451cab57a05ce2f476153631f386fd61ce39877f722e3e1ddf68eaf938eec8102672e307dee823ecd1bbbb9a6532
6
+ metadata.gz: facd4a1bf45bbca5dc44bb60692975aa0109198c7893652678ace43c525b67050514e731c1e9b029619503507fbea994f9a36f6f62d6955de495cf83512b08d3
7
+ data.tar.gz: e12b828bb6f031ed4b7e7ecbffabf2afc5af56eb022726e349c59f736d20c69c8c7dd2f67bede2c593cef32443cd47f8bb7a2e3c098b37efa88fba836488792f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.7.1
data/.travis.yml CHANGED
@@ -1,23 +1,38 @@
1
1
  language: ruby
2
+
2
3
  before_install:
3
4
  - ./spec/travis_build.sh > /dev/null 2>&1
5
+ - export LD_FLAGS=-L$HOME/opt/lib
6
+ - export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:$HOME/opt/lib
7
+ - export CPATH=$CPATH:$HOME/opt/include
8
+
4
9
  rvm:
5
- - 1.9.2
6
- - 1.9.3
7
- - 2.0.0
8
- - 2.1.0
10
+ - 2.5
11
+ - 2.6
12
+ - 2.7
13
+ - 3.0
9
14
  - jruby-19mode
10
15
  - rbx-19mode
11
16
  - ruby-head
12
17
  - jruby-head
18
+ env:
19
+ - LIBWEBP_VERSION=0.4.4
20
+ - LIBWEBP_VERSION=1.0.2
21
+
22
+ cache: bundler
23
+ sudo: false
24
+ dist: xenial
25
+
13
26
  notifications:
14
27
  email: false
28
+
15
29
  branches:
16
30
  only:
17
31
  - master
18
32
  - development
33
+
19
34
  matrix:
20
35
  allow_failures:
21
36
  - rvm: rbx-19mode
22
37
  - rvm: ruby-head
23
- - rvm: jruby-head
38
+ - rvm: jruby-head
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## v0.2.7
2
+
3
+ * Fix build for old libwebp versions
4
+
5
+ ## v0.2.6
6
+
7
+ * Tested on webp 1.0.2
8
+ * Added near_lossless option
9
+
10
+ ## v0.2.5
11
+
12
+ * Fix build for Travis CI docker containers
13
+
14
+ ## v0.2.4
15
+
16
+ * DRY C code and split into files each read/write formats
17
+
1
18
  ## v0.2.3
2
19
 
3
20
  * Fix jpg read in C code
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Webp-ffi
2
2
 
3
- [![Build Status](https://travis-ci.org/le0pard/webp-ffi.png)](https://travis-ci.org/le0pard/webp-ffi)
4
- [![Code Climate](https://codeclimate.com/github/le0pard/webp-ffi.png)](https://codeclimate.com/github/le0pard/webp-ffi)
3
+ [![Build Status](https://travis-ci.com/le0pard/webp-ffi.svg?branch=master)](https://travis-ci.com/le0pard/webp-ffi)
4
+ [![Code Climate](https://codeclimate.com/github/le0pard/webp-ffi/badges/gpa.svg)](https://codeclimate.com/github/le0pard/webp-ffi)
5
5
 
6
6
  Ruby wrapper for libwebp. What is WebP?
7
7
 
@@ -17,7 +17,11 @@ First of all you should have install libraries: libpng, libjpeg and libtiff.
17
17
 
18
18
  For Ubuntu, Debian:
19
19
 
20
- sudo apt-get install libjpeg-dev libpng-dev libtiff-dev
20
+ sudo apt-get install libjpeg-dev libpng-dev libtiff-dev libwebp-dev
21
+
22
+ For Fedora, CentOS:
23
+
24
+ sudo dnf install libjpeg-devel libpng-devel libtiff-devel libwebp-devel
21
25
 
22
26
  For Mac OS:
23
27
 
@@ -27,7 +31,7 @@ or (for MacPorts):
27
31
 
28
32
  sudo port install jpeg libpng tiff
29
33
 
30
- Next, you should [install libwebp](https://developers.google.com/speed/webp/docs/compiling) (if you didn't install it by `brew` in Mac OS). This gem is not support Windows systems (sorry).
34
+ Next, you should [install libwebp](https://developers.google.com/speed/webp/docs/compiling) (if you didn't install it by `brew` in Mac OS or by `apt-get` in Ubuntu or Debian). Webp library version should be >= 0.3.0. This gem is not support Windows systems.
31
35
 
32
36
  ### Final part
33
37
 
@@ -85,6 +89,7 @@ Encode png, jpg or tiff image to webp with options:
85
89
  Possible encode options:
86
90
 
87
91
  * **lossless** (int) - Lossless encoding (0=lossy(default), 1=lossless)
92
+ * **near_lossless** (int) - Use near-lossless image preprocessing (0=maximum preprocessing, 100=no preprocessing(default))
88
93
  * **quality** (float) - between 0 (smallest file) and 100 (biggest)
89
94
  * **method** (int) - quality/speed trade-off (0=fast, 6=slower-better)
90
95
  * **target\_size** (int) - if non-zero, set the desired target size in bytes. Takes precedence over the 'compression' parameter
@@ -142,6 +147,47 @@ Possible decode options:
142
147
  * **crop\_x** (int), **crop\_y** (int), **crop\_w** (int), **crop\_h** (int) - crop picture with the given rectangle
143
148
  * **resize\_w** (int), **resize\_h** (int) - resize picture (after any cropping)
144
149
 
150
+ ## Rails assets pipeline integration
151
+
152
+ For integration with Rails 3+ you can use very simple rake task:
153
+
154
+ ```ruby
155
+ # Place this code in lib/tasks/assets.rake
156
+ require 'webp-ffi'
157
+
158
+ namespace :assets do
159
+ desc "Create .webp versions of assets"
160
+ task :webp => :environment do
161
+ image_types = /\.(?:png|jpe?g)$/
162
+
163
+ public_assets = File.join(
164
+ Rails.root,
165
+ "public",
166
+ Rails.application.config.assets.prefix)
167
+
168
+ Dir["#{public_assets}/**/*"].each do |filename|
169
+ next unless filename =~ image_types
170
+
171
+ mtime = File.mtime(filename)
172
+ webp_file = "#{filename}.webp"
173
+ next if File.exist?(webp_file) && File.mtime(webp_file) >= mtime
174
+ begin
175
+ WebP.encode(filename, webp_file)
176
+ File.utime(mtime, mtime, webp_file)
177
+ puts "Webp converted image #{webp_file}"
178
+ rescue => e
179
+ puts "Webp convertion error of image #{webp_file}. Error info: #{e.message}"
180
+ end
181
+ end
182
+ end
183
+
184
+ # Hook into existing assets:precompile task
185
+ Rake::Task["assets:precompile"].enhance do
186
+ Rake::Task["assets:webp"].invoke
187
+ end
188
+ end
189
+ ```
190
+
145
191
  ## Contributing
146
192
 
147
193
  1. Fork it
data/Rakefile CHANGED
@@ -20,8 +20,8 @@ namespace "ffi-compiler" do
20
20
  c.have_library?('png')
21
21
  c.have_library?('jpeg')
22
22
  c.have_library?('tiff')
23
- c.cflags << "-arch x86_64" if c.platform.mac?
24
- c.ldflags << "-arch x86_64" if c.platform.mac?
23
+ c.ldflags << ENV['LD_FLAGS'] if ENV['LD_FLAGS']
24
+ c.cflags << ENV['C_FLAGS'] if ENV['C_FLAGS']
25
25
  end
26
26
  end
27
27
  task :compile => ["ffi-compiler:default"]
@@ -35,4 +35,4 @@ task :default => [:clean, :compile, :spec]
35
35
 
36
36
  CLEAN.include('ext/**/*{.o,.log,.so,.bundle}')
37
37
  CLEAN.include('lib/**/*{.o,.log,.so,.bundle}')
38
- CLEAN.include('ext/**/Makefile')
38
+ CLEAN.include('ext/**/Makefile')
@@ -15,6 +15,10 @@ FFI::Compiler::CompileTask.new('webp_ffi') do |c|
15
15
  c.have_library?('jpeg')
16
16
  c.have_library?('tiff')
17
17
  # compiler flags
18
- c.cflags << "-arch x86_64" if c.platform.mac?
19
- c.ldflags << "-arch x86_64" if c.platform.mac?
18
+ if c.platform.mac?
19
+ c.cflags << "-arch x86_64"
20
+ c.ldflags << "-arch x86_64"
21
+ end
22
+ c.ldflags << ENV['LD_FLAGS'] if ENV['LD_FLAGS']
23
+ c.cflags << ENV['C_FLAGS'] if ENV['C_FLAGS']
20
24
  end
@@ -0,0 +1,80 @@
1
+ #include "./jpegdec.h"
2
+
3
+ #include <stdio.h>
4
+ #include <jpeglib.h>
5
+ #include <setjmp.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+
9
+ struct my_error_mgr {
10
+ struct jpeg_error_mgr pub;
11
+ jmp_buf setjmp_buffer;
12
+ };
13
+
14
+ static void my_error_exit(j_common_ptr dinfo) {
15
+ struct my_error_mgr* myerr = (struct my_error_mgr*) dinfo->err;
16
+ (*dinfo->err->output_message) (dinfo);
17
+ longjmp(myerr->setjmp_buffer, 1);
18
+ }
19
+
20
+ int UtilReadJPEG(FILE* in_file, WebPPicture* const pic) {
21
+ int ok = 0;
22
+ int stride, width, height;
23
+ uint8_t* rgb = NULL;
24
+ struct jpeg_decompress_struct dinfo;
25
+ struct my_error_mgr jerr;
26
+ JSAMPROW buffer[1];
27
+
28
+ dinfo.err = jpeg_std_error(&jerr.pub);
29
+ jerr.pub.error_exit = my_error_exit;
30
+
31
+ if (setjmp(jerr.setjmp_buffer)) {
32
+ Error:
33
+ jpeg_destroy_decompress(&dinfo);
34
+ goto End;
35
+ }
36
+
37
+ jpeg_create_decompress(&dinfo);
38
+ jpeg_stdio_src(&dinfo, in_file);
39
+ jpeg_read_header(&dinfo, TRUE);
40
+
41
+ dinfo.out_color_space = JCS_RGB;
42
+ dinfo.do_fancy_upsampling = TRUE;
43
+
44
+ jpeg_start_decompress(&dinfo);
45
+
46
+ if (dinfo.output_components != 3) {
47
+ goto Error;
48
+ }
49
+
50
+ width = dinfo.output_width;
51
+ height = dinfo.output_height;
52
+ stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);
53
+
54
+ rgb = (uint8_t*)malloc(stride * height);
55
+ if (rgb == NULL) {
56
+ goto End;
57
+ }
58
+ buffer[0] = (JSAMPLE*)rgb;
59
+
60
+ while (dinfo.output_scanline < dinfo.output_height) {
61
+ if (jpeg_read_scanlines(&dinfo, buffer, 1) != 1) {
62
+ goto End;
63
+ }
64
+ buffer[0] += stride;
65
+ }
66
+
67
+ jpeg_finish_decompress(&dinfo);
68
+ jpeg_destroy_decompress(&dinfo);
69
+
70
+ // WebP conversion.
71
+ pic->width = width;
72
+ pic->height = height;
73
+ ok = WebPPictureImportRGB(pic, rgb, stride);
74
+ if (!ok) goto Error;
75
+
76
+ End:
77
+ free(rgb);
78
+ return ok;
79
+ }
80
+
@@ -0,0 +1,17 @@
1
+ #include <stdio.h>
2
+
3
+ #include "webp/encode.h"
4
+ #include "webp/decode.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ // Reads a JPEG from 'in_file', returning the decoded output in 'pic'.
11
+ // The output is RGB.
12
+ // Returns true on success.
13
+ int UtilReadJPEG(FILE* in_file, struct WebPPicture* const pic);
14
+
15
+ #ifdef __cplusplus
16
+ } // extern "C"
17
+ #endif
@@ -0,0 +1,212 @@
1
+ #include "./pngdec.h"
2
+
3
+ #include <assert.h>
4
+ #include <stdio.h>
5
+ #include <png.h>
6
+ #include <setjmp.h> // note: this must be included *after* png.h
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ static void PNGAPI error_function(png_structp png, png_const_charp dummy) {
11
+ (void)dummy; // remove variable-unused warning
12
+ longjmp(png_jmpbuf(png), 1);
13
+ }
14
+
15
+ int UtilReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) {
16
+ png_structp png;
17
+ png_infop info = NULL;
18
+ png_infop end_info = NULL;
19
+ int color_type, bit_depth, interlaced;
20
+ int has_alpha;
21
+ int num_passes;
22
+ int p;
23
+ int ok = 0;
24
+ png_uint_32 width, height, y;
25
+ int stride;
26
+ uint8_t* rgb = NULL;
27
+
28
+ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
29
+ if (png == NULL) {
30
+ goto End;
31
+ }
32
+
33
+ png_set_error_fn(png, 0, error_function, NULL);
34
+ if (setjmp(png_jmpbuf(png))) {
35
+ Error:
36
+ png_destroy_read_struct(&png, &info, &end_info);
37
+ goto End;
38
+ }
39
+
40
+ info = png_create_info_struct(png);
41
+ if (info == NULL) goto Error;
42
+ end_info = png_create_info_struct(png);
43
+ if (end_info == NULL) goto Error;
44
+
45
+ png_init_io(png, in_file);
46
+ png_read_info(png, info);
47
+ if (!png_get_IHDR(png, info,
48
+ &width, &height, &bit_depth, &color_type, &interlaced,
49
+ NULL, NULL)) goto Error;
50
+
51
+ png_set_strip_16(png);
52
+ png_set_packing(png);
53
+ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
54
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
55
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
56
+ if (bit_depth < 8) {
57
+ png_set_expand_gray_1_2_4_to_8(png);
58
+ }
59
+ png_set_gray_to_rgb(png);
60
+ }
61
+ if (png_get_valid(png, info, PNG_INFO_tRNS)) {
62
+ png_set_tRNS_to_alpha(png);
63
+ has_alpha = 1;
64
+ } else {
65
+ has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
66
+ }
67
+
68
+ if (!keep_alpha) {
69
+ png_set_strip_alpha(png);
70
+ has_alpha = 0;
71
+ }
72
+
73
+ num_passes = png_set_interlace_handling(png);
74
+ png_read_update_info(png, info);
75
+ stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
76
+ rgb = (uint8_t*)malloc(stride * height);
77
+ if (rgb == NULL) goto Error;
78
+ for (p = 0; p < num_passes; ++p) {
79
+ for (y = 0; y < height; ++y) {
80
+ png_bytep row = rgb + y * stride;
81
+ png_read_rows(png, &row, NULL, 1);
82
+ }
83
+ }
84
+ png_read_end(png, end_info);
85
+ png_destroy_read_struct(&png, &info, &end_info);
86
+
87
+ pic->width = width;
88
+ pic->height = height;
89
+ pic->use_argb = 1;
90
+ ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride)
91
+ : WebPPictureImportRGB(pic, rgb, stride);
92
+
93
+ if (!ok) {
94
+ goto Error;
95
+ }
96
+
97
+ End:
98
+ free(rgb);
99
+ return ok;
100
+ }
101
+
102
+
103
+
104
+
105
+
106
+ int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
107
+ const uint32_t width = buffer->width;
108
+ const uint32_t height = buffer->height;
109
+ unsigned char* const rgb = buffer->u.RGBA.rgba;
110
+ const int stride = buffer->u.RGBA.stride;
111
+ const int has_alpha = (buffer->colorspace == MODE_RGBA);
112
+ png_structp png;
113
+ png_infop info;
114
+ png_uint_32 y;
115
+
116
+ png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
117
+ NULL, error_function, NULL);
118
+ if (png == NULL) {
119
+ return 0;
120
+ }
121
+ info = png_create_info_struct(png);
122
+ if (info == NULL) {
123
+ png_destroy_write_struct(&png, NULL);
124
+ return 0;
125
+ }
126
+ if (setjmp(png_jmpbuf(png))) {
127
+ png_destroy_write_struct(&png, &info);
128
+ return 0;
129
+ }
130
+ png_init_io(png, out_file);
131
+ png_set_IHDR(png, info, width, height, 8,
132
+ has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
133
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
134
+ PNG_FILTER_TYPE_DEFAULT);
135
+ png_write_info(png, info);
136
+ for (y = 0; y < height; ++y) {
137
+ png_bytep row = rgb + y * stride;
138
+ png_write_rows(png, &row, 1);
139
+ }
140
+ png_write_end(png, info);
141
+ png_destroy_write_struct(&png, &info);
142
+ return 1;
143
+ }
144
+
145
+
146
+ int UtilWritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
147
+ const uint32_t width = buffer->width;
148
+ const uint32_t height = buffer->height;
149
+ const unsigned char* const rgb = buffer->u.RGBA.rgba;
150
+ const int stride = buffer->u.RGBA.stride;
151
+ const size_t bytes_per_px = alpha ? 4 : 3;
152
+ uint32_t y;
153
+
154
+ if (alpha) {
155
+ fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
156
+ "TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
157
+ } else {
158
+ fprintf(fout, "P6\n%d %d\n255\n", width, height);
159
+ }
160
+ for (y = 0; y < height; ++y) {
161
+ if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
162
+ return 0;
163
+ }
164
+ }
165
+ return 1;
166
+ }
167
+
168
+ int UtilWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
169
+ const uint32_t width = buffer->width;
170
+ const uint32_t height = buffer->height;
171
+ const unsigned char* const a = buffer->u.YUVA.a;
172
+ const int a_stride = buffer->u.YUVA.a_stride;
173
+ uint32_t y;
174
+ assert(a != NULL);
175
+ fprintf(fout, "P5\n%d %d\n255\n", width, height);
176
+ for (y = 0; y < height; ++y) {
177
+ if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
178
+ return 0;
179
+ }
180
+ }
181
+ return 1;
182
+ }
183
+
184
+ int UtilWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
185
+ const int width = buffer->width;
186
+ const int height = buffer->height;
187
+ const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
188
+ // Save a grayscale PGM file using the IMC4 layout
189
+ // (http://www.fourcc.org/yuv.php#IMC4). This is a very
190
+ // convenient format for viewing the samples, esp. for
191
+ // odd dimensions.
192
+ int ok = 1;
193
+ int y;
194
+ const int uv_width = (width + 1) / 2;
195
+ const int uv_height = (height + 1) / 2;
196
+ const int out_stride = (width + 1) & ~1;
197
+ const int a_height = yuv->a ? height : 0;
198
+ fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height + a_height);
199
+ for (y = 0; ok && y < height; ++y) {
200
+ ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1);
201
+ if (width & 1) fputc(0, fout); // padding byte
202
+ }
203
+ for (y = 0; ok && y < uv_height; ++y) {
204
+ ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
205
+ ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
206
+ }
207
+ for (y = 0; ok && y < a_height; ++y) {
208
+ ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1);
209
+ if (width & 1) fputc(0, fout); // padding byte
210
+ }
211
+ return ok;
212
+ }