oily_png 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/oily_png/color.c +18 -3
- data/ext/oily_png/color.h +3 -2
- data/ext/oily_png/oily_png_ext.c +4 -3
- data/ext/oily_png/resampling.c +65 -5
- data/ext/oily_png/resampling.h +3 -1
- data/lib/oily_png.rb +1 -1
- data/oily_png.gemspec +3 -3
- data/spec/resampling_spec.rb +14 -2
- metadata +11 -11
data/ext/oily_png/color.c
CHANGED
@@ -13,7 +13,22 @@ PIXEL oily_png_compose_color(PIXEL fg, PIXEL bg) {
|
|
13
13
|
new_g = INT8_MULTIPLY(A_BYTE(fg), G_BYTE(fg)) + INT8_MULTIPLY(a_com, G_BYTE(bg));
|
14
14
|
new_b = INT8_MULTIPLY(A_BYTE(fg), B_BYTE(fg)) + INT8_MULTIPLY(a_com, B_BYTE(bg));
|
15
15
|
new_a = A_BYTE(fg) + a_com;
|
16
|
-
|
16
|
+
|
17
|
+
return BUILD_PIXEL(new_r, new_g, new_b, new_a);
|
18
|
+
}
|
19
|
+
|
20
|
+
PIXEL oily_png_color_interpolate_quick(PIXEL fg, PIXEL bg, int alpha) {
|
21
|
+
BYTE a_com, new_r, new_g, new_b, new_a;
|
22
|
+
|
23
|
+
if (alpha >= 255) return fg;
|
24
|
+
if (alpha <= 0) return bg;
|
25
|
+
|
26
|
+
a_com = 255 - alpha;
|
27
|
+
new_r = INT8_MULTIPLY(alpha, R_BYTE(fg)) + INT8_MULTIPLY(a_com, R_BYTE(bg));
|
28
|
+
new_g = INT8_MULTIPLY(alpha, G_BYTE(fg)) + INT8_MULTIPLY(a_com, G_BYTE(bg));
|
29
|
+
new_b = INT8_MULTIPLY(alpha, B_BYTE(fg)) + INT8_MULTIPLY(a_com, B_BYTE(bg));
|
30
|
+
new_a = INT8_MULTIPLY(alpha, A_BYTE(fg)) + INT8_MULTIPLY(a_com, A_BYTE(bg));
|
31
|
+
|
17
32
|
return BUILD_PIXEL(new_r, new_g, new_b, new_a);
|
18
33
|
}
|
19
34
|
|
@@ -23,12 +38,12 @@ VALUE oily_png_color_compose_quick(VALUE self, VALUE fg_color, VALUE bg_color) {
|
|
23
38
|
}
|
24
39
|
|
25
40
|
VALUE oily_png_color_r(VALUE self, VALUE value) {
|
26
|
-
UNUSED_PARAMETER(self);
|
41
|
+
UNUSED_PARAMETER(self);
|
27
42
|
return INT2FIX(R_BYTE(NUM2UINT(value)));
|
28
43
|
}
|
29
44
|
|
30
45
|
VALUE oily_png_color_g(VALUE self, VALUE value) {
|
31
|
-
UNUSED_PARAMETER(self);
|
46
|
+
UNUSED_PARAMETER(self);
|
32
47
|
return INT2FIX(G_BYTE(NUM2UINT(value)));
|
33
48
|
}
|
34
49
|
|
data/ext/oily_png/color.h
CHANGED
@@ -9,15 +9,16 @@
|
|
9
9
|
#define BUILD_PIXEL(r, g, b, a) (((PIXEL) (r) << 24) + ((PIXEL) (g) << 16) + ((PIXEL) (b) << 8) + (PIXEL) (a))
|
10
10
|
#define INT8_MULTIPLY(a, b) (((((a) * (b) + 0x80) >> 8) + ((a) * (b) + 0x80)) >> 8)
|
11
11
|
|
12
|
-
/*
|
12
|
+
/*
|
13
13
|
Ruby replacement method for color composition using alpha transparency.
|
14
|
-
|
14
|
+
|
15
15
|
This method should replace ChunkyPNG::Color.compose_quick
|
16
16
|
*/
|
17
17
|
VALUE oily_png_color_compose_quick(VALUE self, VALUE fg_color, VALUE bg_color);
|
18
18
|
|
19
19
|
/* Color composition using alpha transparency. */
|
20
20
|
PIXEL oily_png_compose_color(PIXEL fg, PIXEL bg);
|
21
|
+
PIXEL oily_png_color_interpolate_quick(PIXEL fg, PIXEL bg, int alpha);
|
21
22
|
|
22
23
|
/* Accessors */
|
23
24
|
VALUE oily_png_color_r(VALUE self, VALUE pixel);
|
data/ext/oily_png/oily_png_ext.c
CHANGED
@@ -7,15 +7,16 @@ void Init_oily_png() {
|
|
7
7
|
rb_define_private_method(OilyPNG_Canvas, "steps_residues", oily_png_canvas_steps_residues, 2);
|
8
8
|
rb_define_private_method(OilyPNG_Canvas, "steps", oily_png_canvas_steps, 2);
|
9
9
|
rb_define_method(OilyPNG_Canvas, "resample_nearest_neighbor!", oily_png_canvas_resample_nearest_neighbor_bang, 2);
|
10
|
+
rb_define_method(OilyPNG_Canvas, "resample_bilinear!", oily_png_canvas_resample_bilinear_bang, 2);
|
10
11
|
|
11
12
|
// Setup decoding module
|
12
13
|
VALUE OilyPNG_PNGDecoding = rb_define_module_under(OilyPNG, "PNGDecoding");
|
13
14
|
rb_define_method(OilyPNG_PNGDecoding, "decode_png_image_pass", oily_png_decode_png_image_pass, 6);
|
14
|
-
|
15
|
+
|
15
16
|
// Setup encoding module
|
16
17
|
VALUE OilyPNG_PNGEncoding = rb_define_module_under(OilyPNG, "PNGEncoding");
|
17
18
|
rb_define_method(OilyPNG_PNGEncoding, "encode_png_image_pass_to_stream", oily_png_encode_png_image_pass_to_stream, 4);
|
18
|
-
|
19
|
+
|
19
20
|
// Setup Color module
|
20
21
|
VALUE OilyPNG_Color = rb_define_module_under(OilyPNG, "Color");
|
21
22
|
rb_define_method(OilyPNG_Color, "compose_quick", oily_png_color_compose_quick, 2);
|
@@ -23,7 +24,7 @@ void Init_oily_png() {
|
|
23
24
|
rb_define_method(OilyPNG_Color, "g", oily_png_color_g, 1);
|
24
25
|
rb_define_method(OilyPNG_Color, "b", oily_png_color_b, 1);
|
25
26
|
rb_define_method(OilyPNG_Color, "a", oily_png_color_a, 1);
|
26
|
-
|
27
|
+
|
27
28
|
// Setup Operations module
|
28
29
|
VALUE OilyPNG_Operations = rb_define_module_under(OilyPNG, "Operations");
|
29
30
|
rb_define_method(OilyPNG_Operations, "compose!", oily_png_compose_bang, -1);
|
data/ext/oily_png/resampling.c
CHANGED
@@ -75,10 +75,10 @@ VALUE oily_png_canvas_steps_residues(VALUE self, VALUE v_width, VALUE v_new_widt
|
|
75
75
|
long width = NUM2LONG(v_width);
|
76
76
|
long new_width = NUM2LONG(v_new_width);
|
77
77
|
|
78
|
-
|
78
|
+
|
79
79
|
VALUE ret_steps = rb_ary_new2(new_width);
|
80
80
|
VALUE ret_residues = rb_ary_new2(new_width);
|
81
|
-
|
81
|
+
|
82
82
|
|
83
83
|
long *steps = ALLOC_N(long, new_width);
|
84
84
|
long *residues = ALLOC_N(long, new_width);
|
@@ -91,7 +91,7 @@ VALUE oily_png_canvas_steps_residues(VALUE self, VALUE v_width, VALUE v_new_widt
|
|
91
91
|
rb_ary_store(ret_steps, i, LONG2FIX(steps[i]));
|
92
92
|
rb_ary_store(ret_residues, i, LONG2FIX(residues[i]));
|
93
93
|
}
|
94
|
-
|
94
|
+
|
95
95
|
/* This is an unprotected allocation; it will leak on exception.
|
96
96
|
* However, rb_ary_store should not generate one as we have
|
97
97
|
* pre-allocated the array.
|
@@ -116,7 +116,7 @@ VALUE oily_png_canvas_resample_nearest_neighbor_bang(VALUE self, VALUE v_new_wid
|
|
116
116
|
long new_height = NUM2LONG(v_new_height);
|
117
117
|
|
118
118
|
long self_width = NUM2LONG(rb_funcall(self, rb_intern("width"), 0));
|
119
|
-
long self_height = NUM2LONG(rb_funcall(self, rb_intern("height"), 0));
|
119
|
+
long self_height = NUM2LONG(rb_funcall(self, rb_intern("height"), 0));
|
120
120
|
|
121
121
|
VALUE pixels = rb_ary_new2(new_width*new_height);
|
122
122
|
VALUE source = rb_iv_get(self, "@pixels");
|
@@ -150,4 +150,64 @@ VALUE oily_png_canvas_resample_nearest_neighbor_bang(VALUE self, VALUE v_new_wid
|
|
150
150
|
rb_iv_set(self, "@height", LONG2NUM(new_height));
|
151
151
|
|
152
152
|
return self;
|
153
|
-
}
|
153
|
+
}
|
154
|
+
|
155
|
+
VALUE oily_png_canvas_resample_bilinear_bang(VALUE self, VALUE v_new_width, VALUE v_new_height) {
|
156
|
+
long new_width = NUM2LONG(v_new_width);
|
157
|
+
long new_height = NUM2LONG(v_new_height);
|
158
|
+
|
159
|
+
long self_width = NUM2LONG(rb_funcall(self, rb_intern("width"), 0));
|
160
|
+
long self_height = NUM2LONG(rb_funcall(self, rb_intern("height"), 0));
|
161
|
+
|
162
|
+
VALUE pixels = rb_ary_new2(new_width*new_height);
|
163
|
+
VALUE source = rb_iv_get(self, "@pixels");
|
164
|
+
|
165
|
+
long *index_x = ALLOC_N(long, new_width);
|
166
|
+
long *index_y = ALLOC_N(long, new_height);
|
167
|
+
long *interp_x = ALLOC_N(long, new_width);
|
168
|
+
long *interp_y = ALLOC_N(long, new_height);
|
169
|
+
|
170
|
+
oily_png_generate_steps_residues(self_width, new_width, index_x, interp_x);
|
171
|
+
oily_png_generate_steps_residues(self_height, new_height, index_y, interp_y);
|
172
|
+
|
173
|
+
long index = 0;
|
174
|
+
long x, y;
|
175
|
+
long y1, y2, x1, x2;
|
176
|
+
uint32_t y_residue, x_residue;
|
177
|
+
uint32_t pixel_11, pixel_21, pixel_12, pixel_22;
|
178
|
+
uint32_t pixel_top, pixel_bot;
|
179
|
+
for (y = 0; y < new_height; y++) {
|
180
|
+
y1 = index_y[y] < 0 ? 0 : index_y[y];
|
181
|
+
y2 = y1+1 >= self_height ? self_height-1 : y1+1;
|
182
|
+
y_residue = interp_y[y];
|
183
|
+
|
184
|
+
for (x = 0; x < new_width; x++) {
|
185
|
+
x1 = index_x[x] < 0 ? 0 : index_x[x];
|
186
|
+
x2 = x1+1 >= self_width ? self_height-1 : x1+1;
|
187
|
+
x_residue = interp_x[x];
|
188
|
+
|
189
|
+
pixel_11 = NUM2UINT(rb_ary_entry(source, y1*self_width + x1));
|
190
|
+
pixel_21 = NUM2UINT(rb_ary_entry(source, y1*self_width + x2));
|
191
|
+
pixel_12 = NUM2UINT(rb_ary_entry(source, y2*self_width + x1));
|
192
|
+
pixel_22 = NUM2UINT(rb_ary_entry(source, y2*self_width + x2));
|
193
|
+
|
194
|
+
pixel_top = oily_png_color_interpolate_quick(pixel_21, pixel_11, x_residue);
|
195
|
+
pixel_bot = oily_png_color_interpolate_quick(pixel_22, pixel_12, x_residue);
|
196
|
+
|
197
|
+
rb_ary_store(pixels, index++, UINT2NUM(oily_png_color_interpolate_quick(pixel_bot, pixel_top, y_residue)));
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
xfree(index_x);
|
202
|
+
xfree(index_y);
|
203
|
+
xfree(interp_x);
|
204
|
+
xfree(interp_y);
|
205
|
+
interp_x = NULL;
|
206
|
+
interp_y = NULL;
|
207
|
+
|
208
|
+
rb_iv_set(self, "@pixels", pixels);
|
209
|
+
rb_iv_set(self, "@width", LONG2NUM(new_width));
|
210
|
+
rb_iv_set(self, "@height", LONG2NUM(new_height));
|
211
|
+
|
212
|
+
return self;
|
213
|
+
}
|
data/ext/oily_png/resampling.h
CHANGED
@@ -8,7 +8,7 @@ void oily_png_generate_steps_residues(long width, long new_width, long *steps, l
|
|
8
8
|
|
9
9
|
/*
|
10
10
|
* Generates the interpolation steps through two values.
|
11
|
-
*
|
11
|
+
*
|
12
12
|
* Returns a Ruby Array
|
13
13
|
*/
|
14
14
|
VALUE oily_png_canvas_steps_residues(VALUE self, VALUE width, VALUE new_width);
|
@@ -20,4 +20,6 @@ VALUE oily_png_canvas_steps(VALUE self, VALUE width, VALUE new_width);
|
|
20
20
|
*/
|
21
21
|
VALUE oily_png_canvas_resample_nearest_neighbor_bang(VALUE self, VALUE new_width, VALUE new_height);
|
22
22
|
|
23
|
+
VALUE oily_png_canvas_resample_bilinear_bang(VALUE self, VALUE new_width, VALUE new_height);
|
24
|
+
|
23
25
|
#endif
|
data/lib/oily_png.rb
CHANGED
data/oily_png.gemspec
CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
|
|
4
4
|
|
5
5
|
# Do not change the version and date fields by hand. This will be done
|
6
6
|
# automatically by the gem release script.
|
7
|
-
s.version = "1.0
|
8
|
-
s.date = "2013-
|
7
|
+
s.version = "1.1.0"
|
8
|
+
s.date = "2013-02-15"
|
9
9
|
|
10
10
|
s.summary = "Native mixin to speed up ChunkyPNG"
|
11
11
|
s.description = <<-EOT
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.extensions = ["ext/oily_png/extconf.rb"]
|
20
20
|
s.require_paths = ["lib", "ext"]
|
21
21
|
|
22
|
-
s.add_runtime_dependency('chunky_png', '~> 1.2.
|
22
|
+
s.add_runtime_dependency('chunky_png', '~> 1.2.7')
|
23
23
|
|
24
24
|
s.add_development_dependency('rake')
|
25
25
|
s.add_development_dependency('rake-compiler')
|
data/spec/resampling_spec.rb
CHANGED
@@ -25,15 +25,27 @@ describe OilyPNG::Resampling do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should resample [0,1,2,3] to 99x45 as ChunkyPNG does" do
|
28
|
-
ChunkyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45).should == OilyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45)
|
28
|
+
ChunkyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45).should == OilyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should resample an image to 10x20 as ChunkyPNG does" do
|
32
32
|
@reference.resample_nearest_neighbor(10,20).should == OilyPNG::Canvas.from_canvas(@reference).resample_nearest_neighbor(10,20)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
it "should resample an image to 11x19 as ChunkyPNG does" do
|
36
36
|
@reference.resample_nearest_neighbor(11,19).should == OilyPNG::Canvas.from_canvas(@reference).resample_nearest_neighbor(11,19)
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
describe '#resample_bilinear!' do
|
41
|
+
before(:all) { @reference = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png'))}
|
42
|
+
|
43
|
+
it "should resample an image to 10x20 as ChunkyPNG does" do
|
44
|
+
@reference.resample_bilinear(10,20).should == OilyPNG::Canvas.from_canvas(@reference).resample_bilinear(10,20)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should resample an image to 11x19 as ChunkyPNG does" do
|
48
|
+
@reference.resample_bilinear(11,19).should == OilyPNG::Canvas.from_canvas(@reference).resample_bilinear(11,19)
|
49
|
+
end
|
50
|
+
end
|
39
51
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oily_png
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chunky_png
|
16
|
-
requirement: &
|
16
|
+
requirement: &70329825895620 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.2.
|
21
|
+
version: 1.2.7
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70329825895620
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70329825894740 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70329825894740
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake-compiler
|
38
|
-
requirement: &
|
38
|
+
requirement: &70329825892520 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70329825892520
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70329825890860 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '2'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70329825890860
|
58
58
|
description: ! ' This Ruby C extenstion defines a module that can be included into
|
59
59
|
ChunkyPNG to improve its speed.
|
60
60
|
|