axon 0.0.2 → 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.
- data/CHANGELOG.rdoc +9 -3
- data/README.rdoc +29 -36
- data/Rakefile +26 -21
- data/TODO.rdoc +1 -6
- data/ext/axon/axon.c +6 -15
- data/ext/axon/extconf.rb +19 -9
- data/ext/axon/interpolation.c +147 -0
- data/ext/axon/jpeg.c +1207 -0
- data/ext/axon/png.c +542 -0
- data/lib/axon.rb +235 -32
- data/lib/axon/cropper.rb +80 -18
- data/lib/axon/fit.rb +69 -19
- data/lib/axon/generators.rb +109 -0
- data/lib/axon/scalers.rb +160 -0
- data/test/helper.rb +151 -6
- data/test/reader_tests.rb +37 -82
- data/test/scaler_tests.rb +102 -0
- data/test/stress_helper.rb +58 -0
- data/test/stress_tests.rb +8 -5
- data/test/test_bilinear_scaler.rb +60 -2
- data/test/test_cropper.rb +68 -1
- data/test/test_fit.rb +35 -0
- data/test/test_generators.rb +21 -0
- data/test/test_image.rb +61 -0
- data/test/test_jpeg_reader.rb +96 -94
- data/test/test_jpeg_writer.rb +95 -8
- data/test/test_nearest_neighbor_scaler.rb +28 -4
- data/test/test_png_reader.rb +12 -8
- data/test/test_png_writer.rb +8 -6
- data/test/writer_tests.rb +129 -111
- metadata +71 -128
- data/.gemtest +0 -0
- data/ext/axon/bilinear_interpolation.c +0 -115
- data/ext/axon/interpolation.h +0 -7
- data/ext/axon/jpeg_common.c +0 -118
- data/ext/axon/jpeg_common.h +0 -37
- data/ext/axon/jpeg_native_writer.c +0 -248
- data/ext/axon/jpeg_reader.c +0 -774
- data/ext/axon/nearest_neighbor_interpolation.c +0 -50
- data/ext/axon/png_common.c +0 -21
- data/ext/axon/png_common.h +0 -18
- data/ext/axon/png_native_writer.c +0 -166
- data/ext/axon/png_reader.c +0 -381
- data/lib/axon/axon.so +0 -0
- data/lib/axon/bilinear_scaler.rb +0 -60
- data/lib/axon/jpeg_writer.rb +0 -41
- data/lib/axon/nearest_neighbor_scaler.rb +0 -39
- data/lib/axon/png_writer.rb +0 -35
- data/lib/axon/scaler.rb +0 -41
- data/lib/axon/solid.rb +0 -23
- data/test/_test_readme.rb +0 -34
- data/test/test_exif.rb +0 -39
- data/test/test_generator.rb +0 -10
- data/test/test_icc.rb +0 -18
- data/test/test_jpeg.rb +0 -9
- data/test/test_png.rb +0 -9
data/ext/axon/png.c
ADDED
@@ -0,0 +1,542 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <png.h>
|
3
|
+
|
4
|
+
static ID id_write, id_GRAYSCALE, id_RGB, id_gets, id_width, id_height,
|
5
|
+
id_color_model, id_components, id_read;
|
6
|
+
|
7
|
+
struct png_data {
|
8
|
+
png_structp png_ptr;
|
9
|
+
png_infop info_ptr;
|
10
|
+
size_t lineno;
|
11
|
+
VALUE io;
|
12
|
+
};
|
13
|
+
|
14
|
+
struct io_write {
|
15
|
+
VALUE io;
|
16
|
+
size_t total;
|
17
|
+
};
|
18
|
+
|
19
|
+
static int
|
20
|
+
id_to_color_type(ID rb, int components)
|
21
|
+
{
|
22
|
+
if (rb == id_GRAYSCALE && components == 1) return PNG_COLOR_TYPE_GRAY;
|
23
|
+
else if (rb == id_GRAYSCALE && components == 2) return PNG_COLOR_TYPE_GRAY_ALPHA;
|
24
|
+
else if (rb == id_RGB && components == 3) return PNG_COLOR_TYPE_RGB;
|
25
|
+
else if (rb == id_RGB && components == 4) return PNG_COLOR_TYPE_RGB_ALPHA;
|
26
|
+
|
27
|
+
rb_raise(rb_eRuntimeError, "Color Space not recognized.");
|
28
|
+
}
|
29
|
+
|
30
|
+
static int
|
31
|
+
get_components(png_structp png_ptr, png_infop info_ptr)
|
32
|
+
{
|
33
|
+
switch (png_get_color_type(png_ptr, info_ptr)) {
|
34
|
+
case PNG_COLOR_TYPE_GRAY: return 1;
|
35
|
+
case PNG_COLOR_TYPE_GRAY_ALPHA: return 2;
|
36
|
+
case PNG_COLOR_TYPE_RGB: return 3;
|
37
|
+
case PNG_COLOR_TYPE_RGB_ALPHA: return 4;
|
38
|
+
}
|
39
|
+
|
40
|
+
return 0;
|
41
|
+
}
|
42
|
+
|
43
|
+
static void
|
44
|
+
png_error_fn(png_structp png_ptr, png_const_charp message)
|
45
|
+
{
|
46
|
+
rb_raise(rb_eRuntimeError, "pnglib: %s", message);
|
47
|
+
}
|
48
|
+
|
49
|
+
static void
|
50
|
+
png_warning_fn(png_structp png_ptr, png_const_charp message)
|
51
|
+
{
|
52
|
+
/* do nothing */
|
53
|
+
}
|
54
|
+
|
55
|
+
void
|
56
|
+
write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
57
|
+
{
|
58
|
+
VALUE str, rb_write_len;
|
59
|
+
int write_len;
|
60
|
+
struct io_write *iw;
|
61
|
+
|
62
|
+
if (png_ptr == NULL)
|
63
|
+
return;
|
64
|
+
|
65
|
+
str = rb_str_new(data, length);
|
66
|
+
iw = (struct io_write *)png_get_io_ptr(png_ptr);
|
67
|
+
rb_write_len = rb_funcall(iw->io, id_write, 1, str);
|
68
|
+
|
69
|
+
/* Ruby 1.8.7 makes up odd numbers when running NUM2INT on a symbol */
|
70
|
+
if (TYPE(rb_write_len) == T_SYMBOL)
|
71
|
+
rb_raise(rb_eTypeError, "Number Expected, but got Symbol.");
|
72
|
+
|
73
|
+
write_len = NUM2INT(rb_write_len);
|
74
|
+
|
75
|
+
if ((size_t)write_len != length)
|
76
|
+
rb_raise(rb_eRuntimeError, "Write Error. Wrote %d instead of %d bytes.",
|
77
|
+
write_len, (int)length);
|
78
|
+
iw->total += length;
|
79
|
+
}
|
80
|
+
|
81
|
+
void
|
82
|
+
flush_data(png_structp png_ptr)
|
83
|
+
{
|
84
|
+
/* do nothing */
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE
|
88
|
+
write_scanline(VALUE scan_line, png_structp png_ptr, png_infop info_ptr)
|
89
|
+
{
|
90
|
+
png_uint_32 width;
|
91
|
+
png_byte components;
|
92
|
+
|
93
|
+
if (TYPE(scan_line) != T_STRING)
|
94
|
+
scan_line = rb_obj_as_string(scan_line);
|
95
|
+
|
96
|
+
width = png_get_image_width(png_ptr, info_ptr);
|
97
|
+
components = png_get_channels(png_ptr, info_ptr);
|
98
|
+
if ((png_uint_32)RSTRING_LEN(scan_line) != width * components)
|
99
|
+
rb_raise(rb_eRuntimeError, "Scanline has a bad size. Expected %d * %d but got %d.",
|
100
|
+
(int)width, (int)components, (int)RSTRING_LEN(scan_line));
|
101
|
+
|
102
|
+
png_write_row(png_ptr, (png_bytep)RSTRING_PTR(scan_line));
|
103
|
+
return Qnil;
|
104
|
+
}
|
105
|
+
|
106
|
+
static void
|
107
|
+
write_configure(VALUE image_in, png_structp png_ptr, png_infop info_ptr)
|
108
|
+
{
|
109
|
+
VALUE width, height, color_model, components;
|
110
|
+
int color_type;
|
111
|
+
|
112
|
+
width = rb_funcall(image_in, id_width, 0);
|
113
|
+
/* in 1.8.7, NUM2INT gives funny numbers for Symbols */
|
114
|
+
if (SYMBOL_P(width))
|
115
|
+
rb_raise(rb_eTypeError, "source image has a symbol for width.");
|
116
|
+
|
117
|
+
height = rb_funcall(image_in, id_height, 0);
|
118
|
+
/* in 1.8.7, NUM2INT gives funny numbers for Symbols */
|
119
|
+
if (SYMBOL_P(height))
|
120
|
+
rb_raise(rb_eTypeError, "source image has a symbol for height.");
|
121
|
+
|
122
|
+
components = rb_funcall(image_in, id_components, 0);
|
123
|
+
/* in 1.8.7, NUM2INT gives funny numbers for Symbols */
|
124
|
+
if (SYMBOL_P(components))
|
125
|
+
rb_raise(rb_eTypeError, "source image has a symbol for components.");
|
126
|
+
|
127
|
+
color_model = rb_funcall(image_in, id_color_model, 0);
|
128
|
+
if (SYMBOL_P(color_model))
|
129
|
+
color_type = id_to_color_type(SYM2ID(color_model), NUM2INT(components));
|
130
|
+
else
|
131
|
+
rb_raise(rb_eTypeError, "source image has a non symbol color space");
|
132
|
+
|
133
|
+
png_set_IHDR(png_ptr, info_ptr, NUM2INT(width), NUM2INT(height), 8,
|
134
|
+
color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
135
|
+
PNG_FILTER_TYPE_DEFAULT);
|
136
|
+
}
|
137
|
+
|
138
|
+
static VALUE
|
139
|
+
write_png2(VALUE *args)
|
140
|
+
{
|
141
|
+
struct io_write *data;
|
142
|
+
png_structp png_ptr = (png_structp)args[0];
|
143
|
+
png_infop info_ptr = (png_infop)args[1];
|
144
|
+
VALUE scanline, image_in = args[2];
|
145
|
+
size_t i;
|
146
|
+
|
147
|
+
write_configure(image_in, png_ptr, info_ptr);
|
148
|
+
png_write_info(png_ptr, info_ptr);
|
149
|
+
|
150
|
+
for (i = 0; i < info_ptr->height; i++) {
|
151
|
+
scanline = rb_funcall(image_in, id_gets, 0);
|
152
|
+
write_scanline(scanline, png_ptr, info_ptr);
|
153
|
+
}
|
154
|
+
png_write_end(png_ptr, info_ptr);
|
155
|
+
|
156
|
+
data = (struct io_write *)png_get_io_ptr(png_ptr);
|
157
|
+
|
158
|
+
return INT2FIX(data->total);
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE
|
162
|
+
write_png2_ensure(VALUE *args)
|
163
|
+
{
|
164
|
+
png_structp png_ptr = (png_structp)args[0];
|
165
|
+
png_infop info_ptr = (png_infop)args[1];
|
166
|
+
|
167
|
+
png_destroy_write_struct(&png_ptr, &info_ptr);
|
168
|
+
return Qnil;
|
169
|
+
}
|
170
|
+
|
171
|
+
/*
|
172
|
+
* call-seq:
|
173
|
+
* write(image_in, io_out) -> integer
|
174
|
+
*
|
175
|
+
* Writes the given image +image_in+ to +io_out+ as compressed PNG data.
|
176
|
+
* Returns the number of bytes written.
|
177
|
+
*
|
178
|
+
* image = Axon::Solid.new(200, 300)
|
179
|
+
* io = File.open("test.jpg", "w")
|
180
|
+
* Axon::PNG.write(image, io) #=> 1234
|
181
|
+
*/
|
182
|
+
|
183
|
+
static VALUE
|
184
|
+
write_png(VALUE self, VALUE image_in, VALUE io_out)
|
185
|
+
{
|
186
|
+
VALUE ensure_args[3];
|
187
|
+
png_structp png_ptr;
|
188
|
+
png_infop info_ptr;
|
189
|
+
struct io_write data;
|
190
|
+
|
191
|
+
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
192
|
+
(png_error_ptr)png_error_fn,
|
193
|
+
(png_error_ptr)png_warning_fn);
|
194
|
+
|
195
|
+
if (png_ptr == NULL)
|
196
|
+
rb_raise(rb_eRuntimeError, "unable to allocate a png object");
|
197
|
+
|
198
|
+
info_ptr = png_create_info_struct(png_ptr);
|
199
|
+
if (info_ptr == NULL) {
|
200
|
+
png_destroy_write_struct(&png_ptr, (png_info **)NULL);
|
201
|
+
rb_raise(rb_eRuntimeError, "unable to allocate a png info object");
|
202
|
+
}
|
203
|
+
|
204
|
+
data.io = io_out;
|
205
|
+
data.total = 0;
|
206
|
+
png_set_write_fn(png_ptr, (void *)&data, write_data, flush_data);
|
207
|
+
|
208
|
+
ensure_args[0] = (VALUE)png_ptr;
|
209
|
+
ensure_args[1] = (VALUE)info_ptr;
|
210
|
+
ensure_args[2] = image_in;
|
211
|
+
|
212
|
+
return rb_ensure(write_png2, (VALUE)ensure_args, write_png2_ensure,
|
213
|
+
(VALUE)ensure_args);
|
214
|
+
}
|
215
|
+
|
216
|
+
static void
|
217
|
+
raise_if_locked(struct png_data *reader)
|
218
|
+
{
|
219
|
+
if (reader->lineno)
|
220
|
+
rb_raise(rb_eRuntimeError, "Can't modify a locked Reader");
|
221
|
+
}
|
222
|
+
|
223
|
+
static void
|
224
|
+
free_png(struct png_data *reader)
|
225
|
+
{
|
226
|
+
png_structp png_ptr;
|
227
|
+
png_infop info_ptr;
|
228
|
+
|
229
|
+
png_ptr = reader->png_ptr;
|
230
|
+
info_ptr = reader->info_ptr;
|
231
|
+
|
232
|
+
if (png_ptr && info_ptr)
|
233
|
+
png_destroy_read_struct(&png_ptr, &info_ptr, (png_info **)NULL);
|
234
|
+
else if (png_ptr)
|
235
|
+
png_destroy_read_struct(&png_ptr, (png_info **)NULL, (png_info **)NULL);
|
236
|
+
}
|
237
|
+
|
238
|
+
static void
|
239
|
+
free_reader(struct png_data *reader)
|
240
|
+
{
|
241
|
+
free_png(reader);
|
242
|
+
free(reader);
|
243
|
+
}
|
244
|
+
|
245
|
+
void
|
246
|
+
read_data_fn(png_structp png_ptr, png_bytep data, png_size_t length)
|
247
|
+
{
|
248
|
+
VALUE io, str;
|
249
|
+
size_t read_len;
|
250
|
+
|
251
|
+
if (png_ptr == NULL)
|
252
|
+
return;
|
253
|
+
|
254
|
+
io = (VALUE)png_get_io_ptr(png_ptr);
|
255
|
+
str = rb_funcall(io, id_read, 1, INT2FIX(length));
|
256
|
+
|
257
|
+
if (NIL_P(str))
|
258
|
+
rb_raise(rb_eRuntimeError, "Read Error. Reader returned nil.");
|
259
|
+
|
260
|
+
StringValue(str);
|
261
|
+
read_len = RSTRING_LEN(str);
|
262
|
+
|
263
|
+
if (read_len != length)
|
264
|
+
rb_raise(rb_eRuntimeError, "Read Error. Read %d instead of %d bytes.",
|
265
|
+
(int)read_len, (int)length);
|
266
|
+
|
267
|
+
memcpy(data, RSTRING_PTR(str), read_len);
|
268
|
+
}
|
269
|
+
|
270
|
+
static void
|
271
|
+
mark(struct png_data *reader)
|
272
|
+
{
|
273
|
+
VALUE io = reader->io;
|
274
|
+
|
275
|
+
if (io)
|
276
|
+
rb_gc_mark(io);
|
277
|
+
}
|
278
|
+
|
279
|
+
static void
|
280
|
+
allocate_png(struct png_data *reader)
|
281
|
+
{
|
282
|
+
png_structp png_ptr;
|
283
|
+
png_infop info_ptr;
|
284
|
+
|
285
|
+
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
286
|
+
(png_error_ptr)png_error_fn,
|
287
|
+
(png_error_ptr)png_warning_fn);
|
288
|
+
|
289
|
+
if (png_ptr == NULL)
|
290
|
+
rb_raise(rb_eRuntimeError, "unable to allocate a png object");
|
291
|
+
|
292
|
+
info_ptr = png_create_info_struct(png_ptr);
|
293
|
+
if (info_ptr == NULL) {
|
294
|
+
png_destroy_read_struct(&png_ptr, (png_info **)NULL, (png_info **)NULL);
|
295
|
+
rb_raise(rb_eRuntimeError, "unable to allocate a png info object");
|
296
|
+
}
|
297
|
+
|
298
|
+
reader->png_ptr = png_ptr;
|
299
|
+
reader->info_ptr = info_ptr;
|
300
|
+
}
|
301
|
+
|
302
|
+
static VALUE
|
303
|
+
allocate(VALUE klass)
|
304
|
+
{
|
305
|
+
VALUE self;
|
306
|
+
struct png_data *reader;
|
307
|
+
|
308
|
+
self = Data_Make_Struct(klass, struct png_data, mark, free_reader, reader);
|
309
|
+
allocate_png(reader);
|
310
|
+
|
311
|
+
return self;
|
312
|
+
}
|
313
|
+
|
314
|
+
/*
|
315
|
+
* call-seq:
|
316
|
+
* Reader.new(io_in) -> reader
|
317
|
+
*
|
318
|
+
* Creates a new PNG Reader. +io_in+ must be an IO-like object that responds
|
319
|
+
* to read(size).
|
320
|
+
*
|
321
|
+
* io = File.open("image.png", "r")
|
322
|
+
* reader = Axon::PNG::Reader.new(io)
|
323
|
+
*/
|
324
|
+
|
325
|
+
static VALUE
|
326
|
+
initialize(VALUE self, VALUE io)
|
327
|
+
{
|
328
|
+
struct png_data *reader;
|
329
|
+
png_structp png_ptr;
|
330
|
+
png_infop info_ptr;
|
331
|
+
|
332
|
+
Data_Get_Struct(self, struct png_data, reader);
|
333
|
+
png_ptr = reader->png_ptr;
|
334
|
+
info_ptr = reader->info_ptr;
|
335
|
+
|
336
|
+
raise_if_locked(reader);
|
337
|
+
png_set_read_fn(png_ptr, (void *)io, read_data_fn);
|
338
|
+
reader->io = io;
|
339
|
+
png_read_info(png_ptr, info_ptr);
|
340
|
+
|
341
|
+
return self;
|
342
|
+
}
|
343
|
+
|
344
|
+
/*
|
345
|
+
* call-seq:
|
346
|
+
* reader.components -> number
|
347
|
+
*
|
348
|
+
* Retrieve the number of components as stored in the PNG image.
|
349
|
+
*/
|
350
|
+
|
351
|
+
static VALUE
|
352
|
+
components(VALUE self)
|
353
|
+
{
|
354
|
+
struct png_data *reader;
|
355
|
+
png_structp png_ptr;
|
356
|
+
png_infop info_ptr;
|
357
|
+
int c;
|
358
|
+
|
359
|
+
Data_Get_Struct(self, struct png_data, reader);
|
360
|
+
png_ptr = reader->png_ptr;
|
361
|
+
info_ptr = reader->info_ptr;
|
362
|
+
|
363
|
+
c = get_components(png_ptr, info_ptr);
|
364
|
+
|
365
|
+
if (c == 0)
|
366
|
+
return Qnil;
|
367
|
+
|
368
|
+
return INT2FIX(c);
|
369
|
+
}
|
370
|
+
|
371
|
+
static ID
|
372
|
+
png_color_type_to_id(png_byte color_type)
|
373
|
+
{
|
374
|
+
switch (color_type) {
|
375
|
+
case PNG_COLOR_TYPE_GRAY: return id_GRAYSCALE;
|
376
|
+
case PNG_COLOR_TYPE_GRAY_ALPHA: return id_GRAYSCALE;
|
377
|
+
case PNG_COLOR_TYPE_RGB: return id_RGB;
|
378
|
+
case PNG_COLOR_TYPE_RGB_ALPHA: return id_RGB;
|
379
|
+
}
|
380
|
+
|
381
|
+
rb_raise(rb_eRuntimeError, "PNG Color Type not recognized.");
|
382
|
+
}
|
383
|
+
|
384
|
+
/*
|
385
|
+
* call-seq:
|
386
|
+
* reader.color_model -> symbol
|
387
|
+
*
|
388
|
+
* Returns a symbol representing the color model into which the PNG will be
|
389
|
+
* read.
|
390
|
+
*
|
391
|
+
* Possible color models are: :GRAYSCALE and :RGB.
|
392
|
+
*/
|
393
|
+
|
394
|
+
static VALUE
|
395
|
+
color_model(VALUE self)
|
396
|
+
{
|
397
|
+
struct png_data *reader;
|
398
|
+
png_structp png_ptr;
|
399
|
+
png_infop info_ptr;
|
400
|
+
|
401
|
+
Data_Get_Struct(self, struct png_data, reader);
|
402
|
+
png_ptr = reader->png_ptr;
|
403
|
+
info_ptr = reader->info_ptr;
|
404
|
+
|
405
|
+
return ID2SYM(png_color_type_to_id(png_get_color_type(png_ptr, info_ptr)));
|
406
|
+
}
|
407
|
+
|
408
|
+
/*
|
409
|
+
* call-seq:
|
410
|
+
* gets -> string or nil
|
411
|
+
*
|
412
|
+
* Reads the next scanline of data from the image.
|
413
|
+
*
|
414
|
+
* If the end of the image has been reached, this will return nil.
|
415
|
+
*/
|
416
|
+
|
417
|
+
static VALUE
|
418
|
+
p_gets(VALUE self)
|
419
|
+
{
|
420
|
+
struct png_data *reader;
|
421
|
+
png_structp png_ptr;
|
422
|
+
png_infop info_ptr;
|
423
|
+
int width, components, sl_width;
|
424
|
+
size_t height;
|
425
|
+
VALUE sl;
|
426
|
+
|
427
|
+
Data_Get_Struct(self, struct png_data, reader);
|
428
|
+
png_ptr = reader->png_ptr;
|
429
|
+
info_ptr = reader->info_ptr;
|
430
|
+
|
431
|
+
height = png_get_image_height(png_ptr, info_ptr);
|
432
|
+
if (reader->lineno >= height)
|
433
|
+
return Qnil;
|
434
|
+
|
435
|
+
width = png_get_image_width(png_ptr, info_ptr);
|
436
|
+
components = get_components(png_ptr, info_ptr);
|
437
|
+
sl_width = width * components;
|
438
|
+
|
439
|
+
sl = rb_str_new(0, sl_width);
|
440
|
+
png_read_row(png_ptr, (png_bytep)RSTRING_PTR(sl), (png_bytep)NULL);
|
441
|
+
reader->lineno += 1;
|
442
|
+
|
443
|
+
if (reader->lineno >= height)
|
444
|
+
png_read_end(png_ptr, info_ptr);
|
445
|
+
|
446
|
+
return sl;
|
447
|
+
}
|
448
|
+
|
449
|
+
/*
|
450
|
+
* call-seq:
|
451
|
+
* reader.width -> number
|
452
|
+
*
|
453
|
+
* Retrieve the width of the image.
|
454
|
+
*/
|
455
|
+
|
456
|
+
static VALUE
|
457
|
+
width(VALUE self)
|
458
|
+
{
|
459
|
+
struct png_data *reader;
|
460
|
+
png_structp png_ptr;
|
461
|
+
png_infop info_ptr;
|
462
|
+
|
463
|
+
Data_Get_Struct(self, struct png_data, reader);
|
464
|
+
png_ptr = reader->png_ptr;
|
465
|
+
info_ptr = reader->info_ptr;
|
466
|
+
|
467
|
+
return INT2FIX(png_get_image_width(png_ptr, info_ptr));
|
468
|
+
}
|
469
|
+
|
470
|
+
/*
|
471
|
+
* call-seq:
|
472
|
+
* reader.height -> number
|
473
|
+
*
|
474
|
+
* Retrieve the height of the image.
|
475
|
+
*/
|
476
|
+
|
477
|
+
static VALUE
|
478
|
+
height(VALUE self)
|
479
|
+
{
|
480
|
+
struct png_data *reader;
|
481
|
+
png_structp png_ptr;
|
482
|
+
png_infop info_ptr;
|
483
|
+
|
484
|
+
Data_Get_Struct(self, struct png_data, reader);
|
485
|
+
png_ptr = reader->png_ptr;
|
486
|
+
info_ptr = reader->info_ptr;
|
487
|
+
|
488
|
+
return INT2FIX(png_get_image_height(png_ptr, info_ptr));
|
489
|
+
}
|
490
|
+
|
491
|
+
/*
|
492
|
+
* call-seq:
|
493
|
+
* reader.lineno -> number
|
494
|
+
*
|
495
|
+
* Returns the number of the next line to be read from the image, starting at
|
496
|
+
* 0.
|
497
|
+
*/
|
498
|
+
|
499
|
+
static VALUE
|
500
|
+
lineno(VALUE self)
|
501
|
+
{
|
502
|
+
struct png_data *reader;
|
503
|
+
Data_Get_Struct(self, struct png_data, reader);
|
504
|
+
return INT2FIX(reader->lineno);
|
505
|
+
}
|
506
|
+
|
507
|
+
/*
|
508
|
+
* Document-class: Axon::PNG::Reader
|
509
|
+
*
|
510
|
+
* Read compressed PNG images from an IO.
|
511
|
+
*/
|
512
|
+
|
513
|
+
void
|
514
|
+
Init_PNG()
|
515
|
+
{
|
516
|
+
VALUE mAxon, mPNG, cPNGReader;
|
517
|
+
|
518
|
+
mAxon = rb_define_module("Axon");
|
519
|
+
mPNG = rb_define_module_under(mAxon, "PNG");
|
520
|
+
rb_const_set(mPNG, rb_intern("LIB_VERSION"), INT2FIX(PNG_LIBPNG_VER));
|
521
|
+
rb_define_singleton_method(mPNG, "write", write_png, 2);
|
522
|
+
|
523
|
+
cPNGReader = rb_define_class_under(mPNG, "Reader", rb_cObject);
|
524
|
+
rb_define_alloc_func(cPNGReader, allocate);
|
525
|
+
rb_define_method(cPNGReader, "initialize", initialize, 1);
|
526
|
+
rb_define_method(cPNGReader, "color_model", color_model, 0);
|
527
|
+
rb_define_method(cPNGReader, "components", components, 0);
|
528
|
+
rb_define_method(cPNGReader, "width", width, 0);
|
529
|
+
rb_define_method(cPNGReader, "height", height, 0);
|
530
|
+
rb_define_method(cPNGReader, "gets", p_gets, 0);
|
531
|
+
rb_define_method(cPNGReader, "lineno", lineno, 0);
|
532
|
+
|
533
|
+
id_GRAYSCALE = rb_intern("GRAYSCALE");
|
534
|
+
id_RGB = rb_intern("RGB");
|
535
|
+
id_write = rb_intern("write");
|
536
|
+
id_read = rb_intern("read");
|
537
|
+
id_gets = rb_intern("gets");
|
538
|
+
id_width = rb_intern("width");
|
539
|
+
id_height = rb_intern("height");
|
540
|
+
id_color_model = rb_intern("color_model");
|
541
|
+
id_components = rb_intern("components");
|
542
|
+
}
|