oil 0.0.3 → 0.1.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +14 -46
- data/Rakefile +35 -31
- data/ext/{extconf.rb → oil/extconf.rb} +2 -12
- data/ext/oil/jpeg.c +861 -0
- data/ext/oil/oil.c +10 -0
- data/ext/oil/png.c +337 -0
- data/ext/oil/resample.c +464 -0
- data/ext/oil/resample.h +46 -0
- data/ext/oil/yscaler.c +138 -0
- data/ext/oil/yscaler.h +31 -0
- data/lib/oil.rb +77 -0
- data/test/helper.rb +84 -6
- data/test/test_jpeg.rb +114 -184
- data/test/test_png.rb +105 -169
- metadata +47 -49
- data/ext/oil.c +0 -692
- data/ext/oil.jar +0 -0
data/test/test_png.rb
CHANGED
@@ -1,209 +1,145 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'minitest/autorun'
|
3
2
|
require 'oil'
|
4
3
|
require 'stringio'
|
5
4
|
require 'helper'
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
PNG_DATA = "\
|
6
|
+
class TestPNG < MiniTest::Test
|
7
|
+
# http://garethrees.org/2007/11/14/pngcrush/
|
8
|
+
PNG_DATA = "\
|
11
9
|
\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\
|
12
10
|
\x01\x00\x00\x00\x01\x01\x00\x00\x00\x00\x37\x6E\xF9\x24\x00\x00\x00\x10\x49\
|
13
11
|
\x44\x41\x54\x78\x9C\x62\x60\x01\x00\x00\x00\xFF\xFF\x03\x00\x00\x06\x00\x05\
|
14
|
-
\x57\xBF\xAB\xD4\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
|
12
|
+
\x57\xBF\xAB\xD4\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82".b
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
BIG_PNG = begin
|
15
|
+
resize_string(PNG_DATA, 500, 1000)
|
16
|
+
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
def test_valid
|
19
|
+
o = Oil.new(png_io, 10 ,20)
|
20
|
+
assert_equal 1, o.width
|
21
|
+
assert_equal 1, o.height
|
22
|
+
end
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
def test_bogus_header_chunk
|
25
|
+
str = PNG_DATA.dup
|
26
|
+
str[15] = "\x10"
|
27
|
+
assert_raises(RuntimeError) { resize_string(str) }
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
def test_bogus_body_chunk
|
31
|
+
str = PNG_DATA.dup
|
32
|
+
str[37] = "\x10"
|
33
|
+
assert_raises(RuntimeError) { resize_string(str) }
|
34
|
+
end
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
def test_alloc_each
|
47
|
-
io = PNG.allocate
|
48
|
-
assert_raises(NoMethodError){ io.each{ |f| } }
|
49
|
-
end
|
36
|
+
def test_bogus_end_chunk
|
37
|
+
str = PNG_DATA.dup
|
38
|
+
str[-6] = "\x10"
|
39
|
+
io = StringIO.new(str)
|
40
|
+
o = Oil.new(png_io, 10 ,20)
|
41
|
+
assert_equal 1, o.width
|
42
|
+
assert_equal 1, o.height
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
def test_zero_dim
|
54
|
-
assert_raises(ArgumentError){ resize_string(PNG_DATA, 0, 0) }
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_neg_dim
|
58
|
-
assert_raises(ArgumentError){ resize_string(PNG_DATA, -1231, -123) }
|
59
|
-
end
|
60
|
-
|
61
|
-
# Test io source handler
|
62
|
-
|
63
|
-
def test_io_returns_too_much_data
|
64
|
-
proc = Proc.new do |io, size, buf|
|
65
|
-
str = io.read(size)
|
66
|
-
str = str[0..-2] * 2 if str
|
67
|
-
if buf
|
68
|
-
buf.slice!(0,0) # this empties the buffer
|
69
|
-
buf << str
|
70
|
-
else
|
71
|
-
str
|
72
|
-
end
|
73
|
-
end
|
74
|
-
assert_raises(RuntimeError) { custom_io proc, PNG_DATA }
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_io_does_nothing
|
78
|
-
assert_raises(RuntimeError) { custom_io(nil) }
|
79
|
-
end
|
45
|
+
# Allocation tests
|
80
46
|
|
81
|
-
|
82
|
-
|
83
|
-
assert_raises(CustomError) { custom_io proc }
|
84
|
-
end
|
47
|
+
def test_multiple_initialize_leak
|
48
|
+
o = Oil::PNGReader.allocate
|
85
49
|
|
86
|
-
|
87
|
-
|
88
|
-
catch(:foo){ custom_io proc }
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_io_raises_exception_in_body
|
92
|
-
flag = false
|
93
|
-
proc = Proc.new do |parent, size, buf|
|
94
|
-
raise CustomError if flag
|
95
|
-
flag = true
|
96
|
-
if buf
|
97
|
-
parent.read(size, buf)
|
98
|
-
else
|
99
|
-
parent.read(size)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
assert_raises(CustomError) { custom_io proc, big_png }
|
103
|
-
end
|
50
|
+
o.send(:initialize, png_io)
|
51
|
+
o.each{ |d| }
|
104
52
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
throw :foo if flag
|
109
|
-
flag = true
|
110
|
-
if buf
|
111
|
-
parent.read(size, buf)
|
112
|
-
else
|
113
|
-
parent.read(size)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
catch(:foo){ custom_io proc, big_png }
|
117
|
-
end
|
53
|
+
o.send(:initialize, png_io)
|
54
|
+
o.each{ |d| }
|
55
|
+
end
|
118
56
|
|
119
|
-
|
120
|
-
proc = Proc.new do |parent, size, buf|
|
121
|
-
if buf
|
122
|
-
parent.read(size, buf)
|
123
|
-
buf.slice!(0, 10)
|
124
|
-
else
|
125
|
-
res = parent.read(size)
|
126
|
-
res[10, -1]
|
127
|
-
end
|
128
|
-
end
|
129
|
-
assert_raises(RuntimeError) { custom_io(proc, big_png) }
|
130
|
-
end
|
57
|
+
# Test io
|
131
58
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
else
|
138
|
-
str = parent.read(size)
|
139
|
-
str * 2
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
assert_raises(RuntimeError) { custom_io(proc, big_png) }
|
59
|
+
IO_OFFSETS = [0, 10, 20]#, 8191, 8192, 8193, 12000]
|
60
|
+
|
61
|
+
def iotest(io_class)
|
62
|
+
IO_OFFSETS.each do |i|
|
63
|
+
yield io_class.new(BIG_PNG, :byte_count => i)
|
144
64
|
end
|
65
|
+
end
|
145
66
|
|
146
|
-
|
67
|
+
def resize(io)
|
68
|
+
Oil.new(io, 20, 10).each{ |d| }
|
69
|
+
end
|
147
70
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
PNG.new(io, 200, 200).each { raise CustomError }
|
152
|
-
end
|
71
|
+
def test_io_too_much_data
|
72
|
+
iotest(GrowIO) do |io|
|
73
|
+
assert_raises(RuntimeError) { resize(io) }
|
153
74
|
end
|
75
|
+
end
|
154
76
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
PNG.new(io, 200, 200).each { throw :foo }
|
159
|
-
end
|
77
|
+
def test_io_does_nothing
|
78
|
+
iotest(NilIO) do |io|
|
79
|
+
assert_raises(TypeError) { resize(io) }
|
160
80
|
end
|
81
|
+
end
|
161
82
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
PNG.new(io, 200, 200).each { |d| io_out << d; d.slice!(0, 4) }
|
166
|
-
validate_png(io_out.string)
|
167
|
-
end
|
168
|
-
|
169
|
-
def test_each_enlarges_buffer
|
170
|
-
io = StringIO.new(PNG_DATA)
|
171
|
-
io_out = binary_stringio
|
172
|
-
PNG.new(io, 200, 200).each { |d| io_out << d; d << "foobar" }
|
173
|
-
validate_png(io_out.string)
|
83
|
+
def test_io_raises_exception
|
84
|
+
iotest(RaiseIO) do |io|
|
85
|
+
assert_raises(CustomError) { resize(io) }
|
174
86
|
end
|
87
|
+
end
|
175
88
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
width ||= 100
|
180
|
-
height ||= 200
|
181
|
-
out = binary_stringio
|
182
|
-
PNG.new(io, width, height).each{ |d| out << d }
|
183
|
-
return out.string
|
89
|
+
def test_io_throws
|
90
|
+
iotest(ThrowIO) do |io|
|
91
|
+
assert_throws(:foo) { resize(io) }
|
184
92
|
end
|
93
|
+
end
|
185
94
|
|
186
|
-
|
187
|
-
|
95
|
+
def test_io_shrinks_buffer
|
96
|
+
iotest(ShrinkIO) do |io|
|
97
|
+
assert_raises(RuntimeError) { resize(io) }
|
188
98
|
end
|
99
|
+
end
|
189
100
|
|
190
|
-
|
191
|
-
|
101
|
+
def test_not_string_io
|
102
|
+
iotest(NotStringIO) do |io|
|
103
|
+
assert_raises(TypeError) { resize(io) }
|
192
104
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
105
|
+
end
|
106
|
+
|
107
|
+
# Test yielding
|
108
|
+
|
109
|
+
def test_raise_in_each
|
110
|
+
assert_raises(CustomError) do
|
111
|
+
Oil.new(png_io, 10, 20).each { raise CustomError }
|
197
112
|
end
|
113
|
+
end
|
198
114
|
|
199
|
-
|
200
|
-
|
115
|
+
def test_throw_in_each
|
116
|
+
catch(:foo) do
|
117
|
+
Oil.new(png_io, 10, 20).each { throw :foo }
|
201
118
|
end
|
119
|
+
end
|
202
120
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
121
|
+
def test_each_in_each
|
122
|
+
o = Oil.new(png_io, 10, 20)
|
123
|
+
o.each do |d|
|
124
|
+
assert_raises(RuntimeError){ o.each { |e| } }
|
207
125
|
end
|
208
126
|
end
|
127
|
+
|
128
|
+
def test_each_shrinks_buffer
|
129
|
+
io = StringIO.new(PNG_DATA)
|
130
|
+
io_out = binary_stringio
|
131
|
+
Oil.new(io, 200, 200).each { |d| io_out << d; d.slice!(0, 4) }
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_each_enlarges_buffer
|
135
|
+
io = StringIO.new(PNG_DATA)
|
136
|
+
io_out = binary_stringio
|
137
|
+
Oil.new(io, 200, 200).each { |d| io_out << d; d << "foobar" }
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def png_io
|
143
|
+
StringIO.new(PNG_DATA)
|
144
|
+
end
|
209
145
|
end
|
metadata
CHANGED
@@ -1,63 +1,61 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: oil
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.0.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
6
|
+
authors:
|
7
|
+
- Timothy Elliott
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2012-03-28 00:00:00 Z
|
11
|
+
date: 2014-11-15 00:00:00.000000000 Z
|
14
12
|
dependencies: []
|
15
|
-
|
16
|
-
|
13
|
+
description: Resize JPEG and PNG images, aiming for fast performance and low memory
|
14
|
+
use.
|
17
15
|
email: tle@holymonkey.com
|
18
16
|
executables: []
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
17
|
+
extensions:
|
18
|
+
- ext/oil/extconf.rb
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.rdoc
|
21
|
+
files:
|
22
|
+
- MIT-LICENSE
|
23
|
+
- README.rdoc
|
24
|
+
- Rakefile
|
25
|
+
- ext/oil/extconf.rb
|
26
|
+
- ext/oil/jpeg.c
|
27
|
+
- ext/oil/oil.c
|
28
|
+
- ext/oil/png.c
|
29
|
+
- ext/oil/resample.c
|
30
|
+
- ext/oil/resample.h
|
31
|
+
- ext/oil/yscaler.c
|
32
|
+
- ext/oil/yscaler.h
|
33
|
+
- lib/oil.rb
|
34
|
+
- test/helper.rb
|
35
|
+
- test/test_jpeg.rb
|
36
|
+
- test/test_png.rb
|
33
37
|
homepage: http://github.com/ender672/oil
|
34
|
-
licenses:
|
35
|
-
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata: {}
|
36
41
|
post_install_message:
|
37
42
|
rdoc_options: []
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: "0"
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
53
55
|
requirements: []
|
54
|
-
|
55
56
|
rubyforge_project:
|
56
|
-
rubygems_version:
|
57
|
+
rubygems_version: 2.4.3
|
57
58
|
signing_key:
|
58
|
-
specification_version:
|
59
|
-
summary:
|
60
|
-
test_files:
|
61
|
-
- test/helper.rb
|
62
|
-
- test/test_jpeg.rb
|
63
|
-
- test/test_png.rb
|
59
|
+
specification_version: 4
|
60
|
+
summary: Resize JPEG and PNG images.
|
61
|
+
test_files: []
|
data/ext/oil.c
DELETED
@@ -1,692 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
#include <jpeglib.h>
|
3
|
-
#include <png.h>
|
4
|
-
|
5
|
-
#define BUF_LEN 8192
|
6
|
-
|
7
|
-
static ID id_read, id_seek;
|
8
|
-
|
9
|
-
struct thumbdata {
|
10
|
-
VALUE io;
|
11
|
-
unsigned int width;
|
12
|
-
unsigned int height;
|
13
|
-
};
|
14
|
-
|
15
|
-
static struct jpeg_error_mgr jerr;
|
16
|
-
|
17
|
-
struct jpeg_dest {
|
18
|
-
struct jpeg_destination_mgr mgr;
|
19
|
-
VALUE buffer;
|
20
|
-
};
|
21
|
-
|
22
|
-
struct jpeg_src {
|
23
|
-
struct jpeg_source_mgr mgr;
|
24
|
-
VALUE io;
|
25
|
-
VALUE buffer;
|
26
|
-
};
|
27
|
-
|
28
|
-
struct png_src {
|
29
|
-
VALUE io;
|
30
|
-
VALUE buffer;
|
31
|
-
};
|
32
|
-
|
33
|
-
struct interpolation {
|
34
|
-
long sw;
|
35
|
-
long sh;
|
36
|
-
long dw;
|
37
|
-
long dh;
|
38
|
-
int cmp;
|
39
|
-
void (*read)(char *, void *);
|
40
|
-
void (*write)(char *, void *);
|
41
|
-
void *read_data;
|
42
|
-
void *write_data;
|
43
|
-
};
|
44
|
-
|
45
|
-
struct bitmap {
|
46
|
-
long rowlen;
|
47
|
-
char *cur;
|
48
|
-
};
|
49
|
-
|
50
|
-
/* bitmap source callback */
|
51
|
-
|
52
|
-
static void
|
53
|
-
bitmap_read(char *sl, void *data)
|
54
|
-
{
|
55
|
-
struct bitmap *b = (struct bitmap *)data;
|
56
|
-
memcpy(sl, b->cur, b->rowlen);
|
57
|
-
b->cur += b->rowlen;
|
58
|
-
}
|
59
|
-
|
60
|
-
/* jpeglib error callbacks */
|
61
|
-
|
62
|
-
static void output_message(j_common_ptr cinfo) {}
|
63
|
-
|
64
|
-
static void
|
65
|
-
error_exit(j_common_ptr cinfo)
|
66
|
-
{
|
67
|
-
char buffer[JMSG_LENGTH_MAX];
|
68
|
-
(*cinfo->err->format_message) (cinfo, buffer);
|
69
|
-
rb_raise(rb_eRuntimeError, "jpeglib: %s", buffer);
|
70
|
-
}
|
71
|
-
|
72
|
-
/* jpeglib source callbacks */
|
73
|
-
|
74
|
-
static void term_source(j_decompress_ptr cinfo){};
|
75
|
-
static void init_source(j_decompress_ptr cinfo){};
|
76
|
-
|
77
|
-
static boolean
|
78
|
-
fill_input_buffer(j_decompress_ptr cinfo)
|
79
|
-
{
|
80
|
-
struct jpeg_src *src = (struct jpeg_src *)cinfo->src;
|
81
|
-
VALUE ret, string = src->buffer;
|
82
|
-
long len;
|
83
|
-
char *buf;
|
84
|
-
|
85
|
-
ret = rb_funcall(src->io, id_read, 2, INT2FIX(BUF_LEN), string);
|
86
|
-
len = RSTRING_LEN(string);
|
87
|
-
|
88
|
-
if (!len || NIL_P(ret)) {
|
89
|
-
rb_str_resize(string, 2);
|
90
|
-
buf = RSTRING_PTR(string);
|
91
|
-
buf[0] = 0xFF;
|
92
|
-
buf[1] = JPEG_EOI;
|
93
|
-
len = 2;
|
94
|
-
}
|
95
|
-
src->mgr.next_input_byte = (JOCTET *)RSTRING_PTR(string);
|
96
|
-
src->mgr.bytes_in_buffer = (size_t)len;
|
97
|
-
|
98
|
-
return TRUE;
|
99
|
-
}
|
100
|
-
|
101
|
-
static void
|
102
|
-
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
103
|
-
{
|
104
|
-
struct jpeg_src *src = (struct jpeg_src *)cinfo->src;
|
105
|
-
|
106
|
-
if (num_bytes > (long)src->mgr.bytes_in_buffer) {
|
107
|
-
num_bytes -= (long)src->mgr.bytes_in_buffer;
|
108
|
-
rb_funcall(src->io, id_seek, 2, INT2FIX(num_bytes), INT2FIX(SEEK_CUR));
|
109
|
-
src->mgr.bytes_in_buffer = 0;
|
110
|
-
} else {
|
111
|
-
src->mgr.next_input_byte += (size_t)num_bytes;
|
112
|
-
src->mgr.bytes_in_buffer -= (size_t)num_bytes;
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
/* jpeglib destination callbacks */
|
117
|
-
|
118
|
-
static void init_destination(j_compress_ptr cinfo) {}
|
119
|
-
|
120
|
-
static boolean
|
121
|
-
empty_output_buffer(j_compress_ptr cinfo)
|
122
|
-
{
|
123
|
-
struct jpeg_dest *dest = (struct jpeg_dest *)cinfo->dest;
|
124
|
-
rb_yield(dest->buffer);
|
125
|
-
dest->mgr.next_output_byte = RSTRING_PTR(dest->buffer);
|
126
|
-
dest->mgr.free_in_buffer = RSTRING_LEN(dest->buffer);
|
127
|
-
return TRUE;
|
128
|
-
}
|
129
|
-
|
130
|
-
static void
|
131
|
-
term_destination(j_compress_ptr cinfo)
|
132
|
-
{
|
133
|
-
struct jpeg_dest *dest = (struct jpeg_dest *)cinfo->dest;
|
134
|
-
size_t len = BUF_LEN - dest->mgr.free_in_buffer;
|
135
|
-
|
136
|
-
if (len) {
|
137
|
-
rb_str_resize(dest->buffer, len);
|
138
|
-
rb_yield(dest->buffer);
|
139
|
-
}
|
140
|
-
}
|
141
|
-
|
142
|
-
/* libpng error callbacks */
|
143
|
-
|
144
|
-
static void png_warning_fn(png_structp png_ptr, png_const_charp message) {}
|
145
|
-
|
146
|
-
static void
|
147
|
-
png_error_fn(png_structp png_ptr, png_const_charp message)
|
148
|
-
{
|
149
|
-
rb_raise(rb_eRuntimeError, "pnglib: %s", message);
|
150
|
-
}
|
151
|
-
|
152
|
-
/* libpng io callbacks */
|
153
|
-
|
154
|
-
void png_flush_data(png_structp png_ptr){}
|
155
|
-
|
156
|
-
void
|
157
|
-
png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
158
|
-
{
|
159
|
-
if (!png_ptr) return;
|
160
|
-
rb_yield(rb_str_new(data, length));
|
161
|
-
}
|
162
|
-
|
163
|
-
void
|
164
|
-
png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
165
|
-
{
|
166
|
-
VALUE ret, buf;
|
167
|
-
png_size_t rlen;
|
168
|
-
struct png_src *io_ptr;
|
169
|
-
|
170
|
-
if (!png_ptr) return;
|
171
|
-
io_ptr = (struct png_src *)png_get_io_ptr(png_ptr);
|
172
|
-
buf = io_ptr->buffer;
|
173
|
-
ret = rb_funcall(io_ptr->io, id_read, 2, INT2FIX(length), buf);
|
174
|
-
|
175
|
-
rlen = RSTRING_LEN(buf);
|
176
|
-
if (rlen > length)
|
177
|
-
rb_raise(rb_eRuntimeError, "IO return buffer is too big.");
|
178
|
-
if (!NIL_P(ret)) memcpy(data, RSTRING_PTR(buf), rlen);
|
179
|
-
}
|
180
|
-
|
181
|
-
/* png read/write callbacks */
|
182
|
-
|
183
|
-
static void
|
184
|
-
png_read(char *sl, void *data)
|
185
|
-
{
|
186
|
-
png_read_row((png_structp)data, (png_bytep)sl, (png_bytep)NULL);
|
187
|
-
}
|
188
|
-
|
189
|
-
static void
|
190
|
-
png_write(char *sl, void *data)
|
191
|
-
{
|
192
|
-
png_write_row((png_structp)data, (png_bytep)sl);
|
193
|
-
}
|
194
|
-
|
195
|
-
/* Bilinear Interpolation */
|
196
|
-
|
197
|
-
static void
|
198
|
-
bilinear_get_scanlines(struct interpolation *bi, char **sl1, char **sl2,
|
199
|
-
size_t *next, double ysmp)
|
200
|
-
{
|
201
|
-
int i, j, n, len=bi->cmp * bi->sw - 1;
|
202
|
-
int line=ysmp;
|
203
|
-
char *tmp;
|
204
|
-
|
205
|
-
n = line + 1 - *next;
|
206
|
-
if (line < bi->sh - 1) n++;
|
207
|
-
*next += n;
|
208
|
-
|
209
|
-
for (i=0; i<n; i++) {
|
210
|
-
tmp = *sl1;
|
211
|
-
*sl1 = *sl2;
|
212
|
-
*sl2 = tmp;
|
213
|
-
bi->read(*sl2, bi->read_data);
|
214
|
-
|
215
|
-
for (j=0; j<bi->cmp; j++)
|
216
|
-
sl2[0][len + bi->cmp - j] = sl2[0][len - j];
|
217
|
-
}
|
218
|
-
|
219
|
-
if (line >= bi->sh - 1) *sl1 = *sl2;
|
220
|
-
}
|
221
|
-
|
222
|
-
static void
|
223
|
-
bilinear3(char *sl1, char *sl2, char *sl_out, size_t sw, size_t dw, int cmp,
|
224
|
-
double ysmp)
|
225
|
-
{
|
226
|
-
double xsmp, tx, _tx, p1, p2, p3, p4;
|
227
|
-
unsigned char *c1, *c2, *c3, *c4;
|
228
|
-
size_t xsmp_i, i, j;
|
229
|
-
double xscale_inv, xscale_ctr, ty;
|
230
|
-
|
231
|
-
if (ysmp < 0) ysmp = 0;
|
232
|
-
|
233
|
-
xscale_inv = sw / (float)dw;
|
234
|
-
xscale_ctr = (xscale_inv - 1) / 2;
|
235
|
-
ty = ysmp - (int)ysmp;
|
236
|
-
|
237
|
-
for (i = 0; i < dw; i++) {
|
238
|
-
xsmp = i * xscale_inv + xscale_ctr;
|
239
|
-
if (xsmp < 0) xsmp = 0;
|
240
|
-
xsmp_i = (int)xsmp;
|
241
|
-
|
242
|
-
tx = xsmp - xsmp_i;
|
243
|
-
_tx = 1 - tx;
|
244
|
-
|
245
|
-
p4 = tx * ty;
|
246
|
-
p3 = _tx * ty;
|
247
|
-
p2 = tx - p4;
|
248
|
-
p1 = _tx - p3;
|
249
|
-
|
250
|
-
c1 = sl1 + xsmp_i * cmp;
|
251
|
-
c2 = c1 + cmp;
|
252
|
-
c3 = sl2 + xsmp_i * cmp;
|
253
|
-
c4 = c3 + cmp;
|
254
|
-
|
255
|
-
for (j = 0; j < cmp; j++)
|
256
|
-
*sl_out++ = p1 * c1[j] + p2 * c2[j] + p3 * c3[j] + p4 * c4[j];
|
257
|
-
}
|
258
|
-
}
|
259
|
-
|
260
|
-
static VALUE
|
261
|
-
bilinear2(VALUE _args)
|
262
|
-
{
|
263
|
-
VALUE *args = (VALUE *)_args;
|
264
|
-
struct interpolation *bi=(struct interpolation *)args[0];
|
265
|
-
char *sl1=(char *)args[1], *sl2=(char *)args[2], *sl_out=(char *)args[3];
|
266
|
-
size_t i, line=0;
|
267
|
-
double ysmp, yscale_inv, yscale_ctr;
|
268
|
-
|
269
|
-
yscale_inv = bi->sh / (float)bi->dh;
|
270
|
-
yscale_ctr = (yscale_inv - 1) / 2;
|
271
|
-
|
272
|
-
for (i = 0; i<bi->dh; i++) {
|
273
|
-
ysmp = i * yscale_inv + yscale_ctr;
|
274
|
-
|
275
|
-
bilinear_get_scanlines(bi, &sl1, &sl2, &line, ysmp);
|
276
|
-
bilinear3(sl1, sl2, sl_out, bi->sw, bi->dw, bi->cmp, ysmp);
|
277
|
-
bi->write(sl_out, bi->write_data);
|
278
|
-
}
|
279
|
-
|
280
|
-
return Qnil;
|
281
|
-
}
|
282
|
-
|
283
|
-
static void
|
284
|
-
bilinear(struct interpolation *bi)
|
285
|
-
{
|
286
|
-
VALUE args[4];
|
287
|
-
int state, in_len;
|
288
|
-
char *sl1, *sl2, *sl_out;
|
289
|
-
|
290
|
-
in_len = (bi->sw + 1) * bi->cmp;
|
291
|
-
sl1 = malloc(in_len);
|
292
|
-
sl2 = malloc(in_len);
|
293
|
-
sl_out = malloc(bi->dw * bi->cmp);
|
294
|
-
|
295
|
-
args[0] = (VALUE)bi;
|
296
|
-
args[1] = (VALUE)sl1;
|
297
|
-
args[2] = (VALUE)sl2;
|
298
|
-
args[3] = (VALUE)sl_out;
|
299
|
-
rb_protect(bilinear2, (VALUE)args, &state);
|
300
|
-
|
301
|
-
free(sl1);
|
302
|
-
free(sl2);
|
303
|
-
free(sl_out);
|
304
|
-
|
305
|
-
if (state) rb_jump_tag(state);
|
306
|
-
}
|
307
|
-
|
308
|
-
/* helper functions */
|
309
|
-
|
310
|
-
static void
|
311
|
-
fix_ratio(unsigned int sw, unsigned int sh, unsigned int *dw, unsigned int *dh)
|
312
|
-
{
|
313
|
-
double x, y;
|
314
|
-
x = *dw / (float)sw;
|
315
|
-
y = *dh / (float)sh;
|
316
|
-
if (x<y) *dh = sh * x;
|
317
|
-
else *dw = sw * y;
|
318
|
-
if (!*dh) *dh = 1;
|
319
|
-
if (!*dw) *dw = 1;
|
320
|
-
}
|
321
|
-
|
322
|
-
/* jpeg helper functions */
|
323
|
-
|
324
|
-
static void
|
325
|
-
jpeg_set_output_header(j_compress_ptr cinfo, j_decompress_ptr dinfo)
|
326
|
-
{
|
327
|
-
cinfo->input_components = dinfo->output_components;
|
328
|
-
cinfo->in_color_space = dinfo->out_color_space;
|
329
|
-
jpeg_set_defaults(cinfo);
|
330
|
-
}
|
331
|
-
|
332
|
-
static void
|
333
|
-
jpeg_pre_scale(j_compress_ptr cinfo, j_decompress_ptr dinfo)
|
334
|
-
{
|
335
|
-
int inv_scale = dinfo->output_width / cinfo->image_width;
|
336
|
-
|
337
|
-
if (inv_scale >= 8) dinfo->scale_denom = 8;
|
338
|
-
else if (inv_scale >= 4) dinfo->scale_denom = 4;
|
339
|
-
else if (inv_scale >= 2) dinfo->scale_denom = 2;
|
340
|
-
jpeg_calc_output_dimensions(dinfo);
|
341
|
-
}
|
342
|
-
|
343
|
-
static void
|
344
|
-
jpeg_read(char *sl, void *data)
|
345
|
-
{
|
346
|
-
jpeg_read_scanlines((j_decompress_ptr)data, (JSAMPROW *)&sl, 1);
|
347
|
-
}
|
348
|
-
|
349
|
-
static void
|
350
|
-
jpeg_write(char *sl, void *data)
|
351
|
-
{
|
352
|
-
jpeg_write_scanlines((j_compress_ptr)data, (JSAMPROW *)&sl, 1);
|
353
|
-
}
|
354
|
-
|
355
|
-
static VALUE
|
356
|
-
jpeg_each3(VALUE _args)
|
357
|
-
{
|
358
|
-
VALUE *args = (VALUE *)_args;
|
359
|
-
j_decompress_ptr dinfo = (j_decompress_ptr)args[0];
|
360
|
-
j_compress_ptr cinfo = (j_compress_ptr)args[1];
|
361
|
-
struct interpolation intrp;
|
362
|
-
|
363
|
-
jpeg_read_header(dinfo, TRUE);
|
364
|
-
jpeg_calc_output_dimensions(dinfo);
|
365
|
-
jpeg_set_output_header(cinfo, dinfo);
|
366
|
-
fix_ratio(dinfo->output_width, dinfo->output_height, &cinfo->image_width,
|
367
|
-
&cinfo->image_height);
|
368
|
-
jpeg_pre_scale(cinfo, dinfo);
|
369
|
-
|
370
|
-
jpeg_start_compress(cinfo, TRUE);
|
371
|
-
jpeg_start_decompress(dinfo);
|
372
|
-
|
373
|
-
intrp.sw = dinfo->output_width;
|
374
|
-
intrp.sh = dinfo->output_height;
|
375
|
-
intrp.dw = cinfo->image_width;
|
376
|
-
intrp.dh = cinfo->image_height;
|
377
|
-
intrp.cmp = dinfo->output_components;
|
378
|
-
intrp.read = jpeg_read;
|
379
|
-
intrp.write = jpeg_write;
|
380
|
-
intrp.read_data = dinfo;
|
381
|
-
intrp.write_data = cinfo;
|
382
|
-
|
383
|
-
bilinear(&intrp);
|
384
|
-
|
385
|
-
jpeg_abort_decompress(dinfo);
|
386
|
-
jpeg_finish_compress(cinfo);
|
387
|
-
|
388
|
-
return Qnil;
|
389
|
-
}
|
390
|
-
|
391
|
-
static void
|
392
|
-
jpeg_each2(struct thumbdata *data, struct jpeg_src *src, struct jpeg_dest *dest)
|
393
|
-
{
|
394
|
-
int state;
|
395
|
-
VALUE args[2];
|
396
|
-
struct jpeg_decompress_struct dinfo;
|
397
|
-
struct jpeg_compress_struct cinfo;
|
398
|
-
|
399
|
-
dinfo.err = cinfo.err = &jerr;
|
400
|
-
|
401
|
-
jpeg_create_compress(&cinfo);
|
402
|
-
cinfo.dest = &dest->mgr;
|
403
|
-
cinfo.image_width = data->width;
|
404
|
-
cinfo.image_height = data->height;
|
405
|
-
|
406
|
-
jpeg_create_decompress(&dinfo);
|
407
|
-
dinfo.src = &src->mgr;
|
408
|
-
|
409
|
-
args[0] = (VALUE)&dinfo;
|
410
|
-
args[1] = (VALUE)&cinfo;
|
411
|
-
rb_protect(jpeg_each3, (VALUE)args, &state);
|
412
|
-
|
413
|
-
jpeg_destroy_decompress(&dinfo);
|
414
|
-
jpeg_destroy_compress(&cinfo);
|
415
|
-
|
416
|
-
if (state) rb_jump_tag(state);
|
417
|
-
}
|
418
|
-
|
419
|
-
/* Ruby allocator, deallocator, mark, and methods */
|
420
|
-
|
421
|
-
static void
|
422
|
-
deallocate(struct thumbdata *data)
|
423
|
-
{
|
424
|
-
free(data);
|
425
|
-
}
|
426
|
-
|
427
|
-
static void
|
428
|
-
mark(struct thumbdata *data)
|
429
|
-
{
|
430
|
-
if (!NIL_P(data->io))
|
431
|
-
rb_gc_mark(data->io);
|
432
|
-
}
|
433
|
-
|
434
|
-
static VALUE
|
435
|
-
allocate(VALUE klass)
|
436
|
-
{
|
437
|
-
struct thumbdata *data;
|
438
|
-
return Data_Make_Struct(klass, struct thumbdata, mark, deallocate, data);
|
439
|
-
}
|
440
|
-
|
441
|
-
/*
|
442
|
-
* call-seq:
|
443
|
-
* Class.new(io, width, height) -> obj
|
444
|
-
*
|
445
|
-
* Creates a new resizer. +io_in+ must be an IO-like object that responds to
|
446
|
-
* #read(size, buffer) and #seek(size).
|
447
|
-
*
|
448
|
-
* The resulting image will be scaled to fit in the box given by +width+ and
|
449
|
-
* +height+ while preserving the original aspect ratio.
|
450
|
-
*/
|
451
|
-
|
452
|
-
static VALUE
|
453
|
-
initialize(VALUE self, VALUE io, VALUE rb_width, VALUE rb_height)
|
454
|
-
{
|
455
|
-
int width=FIX2INT(rb_width), height=FIX2INT(rb_height);
|
456
|
-
struct thumbdata *data;
|
457
|
-
|
458
|
-
if (width<1 || height<1) rb_raise(rb_eArgError, "Dimensions must be > 0");
|
459
|
-
|
460
|
-
Data_Get_Struct(self, struct thumbdata, data);
|
461
|
-
data->io = io;
|
462
|
-
data->width = width;
|
463
|
-
data->height = height;
|
464
|
-
|
465
|
-
return self;
|
466
|
-
}
|
467
|
-
|
468
|
-
/*
|
469
|
-
* call-seq:
|
470
|
-
* jpeg.each(&block) -> self
|
471
|
-
*
|
472
|
-
* Yields a series of binary strings that make up the resized JPEG image.
|
473
|
-
*/
|
474
|
-
|
475
|
-
static VALUE
|
476
|
-
jpeg_each(VALUE self)
|
477
|
-
{
|
478
|
-
struct jpeg_src src;
|
479
|
-
struct jpeg_dest dest;
|
480
|
-
struct thumbdata *data;
|
481
|
-
Data_Get_Struct(self, struct thumbdata, data);
|
482
|
-
|
483
|
-
memset(&src, 0, sizeof(struct jpeg_src));
|
484
|
-
src.io = data->io;
|
485
|
-
src.buffer = rb_str_new(0, 0);
|
486
|
-
src.mgr.init_source = init_source;
|
487
|
-
src.mgr.fill_input_buffer = fill_input_buffer;
|
488
|
-
src.mgr.skip_input_data = skip_input_data;
|
489
|
-
src.mgr.resync_to_restart = jpeg_resync_to_restart;
|
490
|
-
src.mgr.term_source = term_source;
|
491
|
-
|
492
|
-
memset(&dest, 0, sizeof(struct jpeg_dest));
|
493
|
-
dest.buffer = rb_str_new(0, BUF_LEN);
|
494
|
-
dest.mgr.next_output_byte = RSTRING_PTR(dest.buffer);
|
495
|
-
dest.mgr.free_in_buffer = BUF_LEN;
|
496
|
-
dest.mgr.init_destination = init_destination;
|
497
|
-
dest.mgr.empty_output_buffer = empty_output_buffer;
|
498
|
-
dest.mgr.term_destination = term_destination;
|
499
|
-
|
500
|
-
jpeg_each2(data, &src, &dest);
|
501
|
-
|
502
|
-
return self;
|
503
|
-
}
|
504
|
-
|
505
|
-
static void
|
506
|
-
png_normalize_input(png_structp read_ptr, png_infop read_i_ptr)
|
507
|
-
{
|
508
|
-
png_byte ctype;
|
509
|
-
int bit_depth;
|
510
|
-
|
511
|
-
bit_depth = png_get_bit_depth(read_ptr, read_i_ptr);
|
512
|
-
ctype = png_get_color_type(read_ptr, read_i_ptr);
|
513
|
-
|
514
|
-
if (ctype == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
515
|
-
png_set_gray_1_2_4_to_8(read_ptr);
|
516
|
-
|
517
|
-
if (bit_depth < 8)
|
518
|
-
png_set_packing(read_ptr);
|
519
|
-
else if (bit_depth == 16)
|
520
|
-
#if PNG_LIBPNG_VER >= 10504
|
521
|
-
png_set_scale_16(read_ptr);
|
522
|
-
#else
|
523
|
-
png_set_strip_16(read_ptr);
|
524
|
-
#endif
|
525
|
-
|
526
|
-
if (png_get_valid(read_ptr, read_i_ptr, PNG_INFO_tRNS))
|
527
|
-
png_set_tRNS_to_alpha(read_ptr);
|
528
|
-
|
529
|
-
if (ctype == PNG_COLOR_TYPE_PALETTE)
|
530
|
-
png_set_palette_to_rgb(read_ptr);
|
531
|
-
|
532
|
-
png_read_update_info(read_ptr, read_i_ptr);
|
533
|
-
}
|
534
|
-
|
535
|
-
static VALUE
|
536
|
-
png_interlaced2(VALUE arg)
|
537
|
-
{
|
538
|
-
bilinear((struct interpolation *)arg);
|
539
|
-
}
|
540
|
-
|
541
|
-
static void
|
542
|
-
png_interlaced(png_structp rpng, struct interpolation *intrp)
|
543
|
-
{
|
544
|
-
struct bitmap b;
|
545
|
-
png_bytep *rows;
|
546
|
-
char *data;
|
547
|
-
int i, state;
|
548
|
-
|
549
|
-
b.rowlen = intrp->sw * intrp->cmp;
|
550
|
-
data = malloc(b.rowlen * intrp->sh);
|
551
|
-
b.cur = data;
|
552
|
-
|
553
|
-
rows = malloc(intrp->sh * sizeof(png_bytep));
|
554
|
-
for (i=0; i<intrp->sh; i++)
|
555
|
-
rows[i] = data + (i * b.rowlen);
|
556
|
-
|
557
|
-
png_read_image(rpng, rows);
|
558
|
-
|
559
|
-
intrp->read = bitmap_read;
|
560
|
-
intrp->read_data = (void *)&b;
|
561
|
-
|
562
|
-
rb_protect(png_interlaced2, (VALUE)intrp, &state);
|
563
|
-
|
564
|
-
free(rows);
|
565
|
-
free(data);
|
566
|
-
|
567
|
-
if (state) rb_jump_tag(state);
|
568
|
-
}
|
569
|
-
|
570
|
-
static VALUE
|
571
|
-
png_each2(VALUE _args)
|
572
|
-
{
|
573
|
-
VALUE *args = (VALUE *)_args;
|
574
|
-
png_structp write_ptr=(png_structp)args[0];
|
575
|
-
png_infop write_i_ptr=(png_infop)args[1];
|
576
|
-
png_structp read_ptr=(png_structp)args[2];
|
577
|
-
png_infop read_i_ptr=(png_infop)args[3];
|
578
|
-
struct thumbdata *thumb=(struct thumbdata *)args[4];
|
579
|
-
struct interpolation intrp;
|
580
|
-
png_byte ctype;
|
581
|
-
|
582
|
-
png_read_info(read_ptr, read_i_ptr);
|
583
|
-
png_normalize_input(read_ptr, read_i_ptr);
|
584
|
-
ctype = png_get_color_type(read_ptr, read_i_ptr);
|
585
|
-
|
586
|
-
intrp.sw = png_get_image_width(read_ptr, read_i_ptr);
|
587
|
-
intrp.sh = png_get_image_height(read_ptr, read_i_ptr);
|
588
|
-
fix_ratio(intrp.sw, intrp.sh, &thumb->width, &thumb->height);
|
589
|
-
png_set_IHDR(write_ptr, write_i_ptr, thumb->width, thumb->height, 8,
|
590
|
-
ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
591
|
-
PNG_FILTER_TYPE_DEFAULT);
|
592
|
-
png_write_info(write_ptr, write_i_ptr);
|
593
|
-
|
594
|
-
switch (ctype) {
|
595
|
-
case PNG_COLOR_TYPE_GRAY: intrp.cmp = 1; break;
|
596
|
-
case PNG_COLOR_TYPE_GRAY_ALPHA: intrp.cmp = 2; break;
|
597
|
-
case PNG_COLOR_TYPE_RGB: intrp.cmp = 3; break;
|
598
|
-
case PNG_COLOR_TYPE_RGB_ALPHA: intrp.cmp = 4; break;
|
599
|
-
default: rb_raise(rb_eRuntimeError, "png color type not supported.");
|
600
|
-
}
|
601
|
-
|
602
|
-
intrp.dw = thumb->width;
|
603
|
-
intrp.dh = thumb->height;
|
604
|
-
intrp.write = png_write;
|
605
|
-
intrp.write_data = write_ptr;
|
606
|
-
|
607
|
-
switch (png_get_interlace_type(read_ptr, read_i_ptr)) {
|
608
|
-
case PNG_INTERLACE_NONE:
|
609
|
-
intrp.read = png_read;
|
610
|
-
intrp.read_data = read_ptr;
|
611
|
-
bilinear(&intrp);
|
612
|
-
break;
|
613
|
-
case PNG_INTERLACE_ADAM7:
|
614
|
-
png_interlaced(read_ptr, &intrp);
|
615
|
-
break;
|
616
|
-
default: rb_raise(rb_eRuntimeError, "png interlace type not supported.");
|
617
|
-
}
|
618
|
-
|
619
|
-
png_write_end(write_ptr, write_i_ptr);
|
620
|
-
|
621
|
-
return Qnil;
|
622
|
-
}
|
623
|
-
|
624
|
-
/*
|
625
|
-
* call-seq:
|
626
|
-
* png.each(&block) -> self
|
627
|
-
*
|
628
|
-
* Yields a series of binary strings that make up the resized PNG image.
|
629
|
-
*/
|
630
|
-
|
631
|
-
static VALUE
|
632
|
-
png_each(VALUE self)
|
633
|
-
{
|
634
|
-
int state;
|
635
|
-
VALUE args[5];
|
636
|
-
png_structp read_ptr, write_ptr;
|
637
|
-
png_infop read_i_ptr, write_i_ptr;
|
638
|
-
struct png_src src;
|
639
|
-
struct thumbdata *thumb;
|
640
|
-
Data_Get_Struct(self, struct thumbdata, thumb);
|
641
|
-
|
642
|
-
write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
643
|
-
(png_error_ptr)png_error_fn,
|
644
|
-
(png_error_ptr)png_warning_fn);
|
645
|
-
write_i_ptr = png_create_info_struct(write_ptr);
|
646
|
-
png_set_write_fn(write_ptr, NULL, png_write_data, png_flush_data);
|
647
|
-
|
648
|
-
src.io = thumb->io;
|
649
|
-
src.buffer = rb_str_new(0, 0);
|
650
|
-
|
651
|
-
read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
652
|
-
(png_error_ptr)png_error_fn,
|
653
|
-
(png_error_ptr)png_warning_fn);
|
654
|
-
read_i_ptr = png_create_info_struct(read_ptr);
|
655
|
-
png_set_read_fn(read_ptr, (void *)&src, png_read_data);
|
656
|
-
|
657
|
-
args[0] = (VALUE)write_ptr;
|
658
|
-
args[1] = (VALUE)write_i_ptr;
|
659
|
-
args[2] = (VALUE)read_ptr;
|
660
|
-
args[3] = (VALUE)read_i_ptr;
|
661
|
-
args[4] = (VALUE)thumb;
|
662
|
-
rb_protect(png_each2, (VALUE)args, &state);
|
663
|
-
|
664
|
-
png_destroy_read_struct(&read_ptr, &read_i_ptr, (png_info **)NULL);
|
665
|
-
png_destroy_write_struct(&write_ptr, &write_i_ptr);
|
666
|
-
|
667
|
-
if (state) rb_jump_tag(state);
|
668
|
-
return self;
|
669
|
-
}
|
670
|
-
|
671
|
-
void
|
672
|
-
Init_oil(void)
|
673
|
-
{
|
674
|
-
VALUE mOil = rb_define_module("Oil");
|
675
|
-
|
676
|
-
VALUE cJPEG = rb_define_class_under(mOil, "JPEG", rb_cObject);
|
677
|
-
rb_define_alloc_func(cJPEG, allocate);
|
678
|
-
rb_define_method(cJPEG, "initialize", initialize, 3);
|
679
|
-
rb_define_method(cJPEG, "each", jpeg_each, 0);
|
680
|
-
|
681
|
-
VALUE cPNG = rb_define_class_under(mOil, "PNG", rb_cObject);
|
682
|
-
rb_define_alloc_func(cPNG, allocate);
|
683
|
-
rb_define_method(cPNG, "initialize", initialize, 3);
|
684
|
-
rb_define_method(cPNG, "each", png_each, 0);
|
685
|
-
|
686
|
-
jpeg_std_error(&jerr);
|
687
|
-
jerr.error_exit = error_exit;
|
688
|
-
jerr.output_message = output_message;
|
689
|
-
|
690
|
-
id_read = rb_intern("read");
|
691
|
-
id_seek = rb_intern("seek");
|
692
|
-
}
|