axon 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,50 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
|
3
|
-
static ID id_image, id_components, id_width_ratio, id_width;
|
4
|
-
|
5
|
-
/*
|
6
|
-
* call-seq:
|
7
|
-
* image.interpolate_scanline(original_scanlines, q) -> interpolated_scanline
|
8
|
-
*/
|
9
|
-
static VALUE
|
10
|
-
interpolate_scanline(VALUE self, VALUE rb_scanline)
|
11
|
-
{
|
12
|
-
VALUE rb_components, rb_width_ratio, rb_dest_sl, rb_image, rb_width;
|
13
|
-
double width_ratio;
|
14
|
-
unsigned char *scanline, *dest_sl;
|
15
|
-
size_t width, components, i, j;
|
16
|
-
|
17
|
-
rb_width = rb_ivar_get(self, id_width);
|
18
|
-
width = FIX2INT(rb_width);
|
19
|
-
|
20
|
-
rb_image = rb_ivar_get(self, id_image);
|
21
|
-
rb_components = rb_funcall(rb_image, id_components, 0);
|
22
|
-
components = FIX2INT(rb_components);
|
23
|
-
|
24
|
-
rb_width_ratio = rb_ivar_get(self, id_width_ratio);
|
25
|
-
width_ratio = NUM2DBL(rb_width_ratio);
|
26
|
-
|
27
|
-
scanline = RSTRING_PTR(rb_scanline);
|
28
|
-
|
29
|
-
rb_dest_sl = rb_str_new(0, width * components);
|
30
|
-
dest_sl = RSTRING_PTR(rb_dest_sl);
|
31
|
-
|
32
|
-
for (i = 0; i < width; i++)
|
33
|
-
for (j = 0; j < components; j++)
|
34
|
-
dest_sl[i * components + j] = scanline[(int)(i / width_ratio)];
|
35
|
-
|
36
|
-
return rb_dest_sl;
|
37
|
-
}
|
38
|
-
|
39
|
-
void
|
40
|
-
Init_nearest_neighbor_interpolation()
|
41
|
-
{
|
42
|
-
VALUE mAxon = rb_define_module("Axon");
|
43
|
-
VALUE mNearestNeighborScaling = rb_define_module_under(mAxon, "NearestNeighborScaling");
|
44
|
-
rb_define_method(mNearestNeighborScaling, "interpolate_scanline", interpolate_scanline, 1);
|
45
|
-
|
46
|
-
id_width_ratio = rb_intern("@width_ratio");
|
47
|
-
id_image = rb_intern("@image");
|
48
|
-
id_components = rb_intern("components");
|
49
|
-
id_width = rb_intern("@width");
|
50
|
-
}
|
data/ext/axon/png_common.c
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
#include "png_common.h"
|
2
|
-
|
3
|
-
void
|
4
|
-
png_error_fn(png_structp png_ptr, png_const_charp message)
|
5
|
-
{
|
6
|
-
rb_raise(rb_eRuntimeError, "pnglib: %s", message);
|
7
|
-
}
|
8
|
-
|
9
|
-
void
|
10
|
-
png_warning_fn(png_structp png_ptr, png_const_charp message)
|
11
|
-
{
|
12
|
-
/* do nothing */
|
13
|
-
}
|
14
|
-
|
15
|
-
void
|
16
|
-
Init_png()
|
17
|
-
{
|
18
|
-
VALUE mAxon = rb_define_module("Axon");
|
19
|
-
rb_const_set(mAxon, rb_intern("PNG_LIB_VERSION"),
|
20
|
-
INT2FIX(PNG_LIBPNG_VER));
|
21
|
-
}
|
data/ext/axon/png_common.h
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#ifndef AXON_PNG_COMMON_H
|
2
|
-
#define AXON_PNG_COMMON_H
|
3
|
-
|
4
|
-
#include <ruby.h>
|
5
|
-
#include <png.h>
|
6
|
-
|
7
|
-
#ifndef HAVE_RB_BLOCK_CALL
|
8
|
-
#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, arg1, arg5, arg6)
|
9
|
-
#endif
|
10
|
-
|
11
|
-
void png_error_fn(png_structp, png_const_charp);
|
12
|
-
void png_warning_fn(png_structp, png_const_charp);
|
13
|
-
|
14
|
-
void Init_png();
|
15
|
-
void Init_png_native_writer();
|
16
|
-
void Init_png_reader();
|
17
|
-
|
18
|
-
#endif
|
@@ -1,166 +0,0 @@
|
|
1
|
-
#include "png_common.h"
|
2
|
-
|
3
|
-
static ID id_write, id_GRAYSCALE, id_RGB, id_image, id_each, id_width,
|
4
|
-
id_height, id_color_model, id_components;
|
5
|
-
|
6
|
-
void
|
7
|
-
write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
8
|
-
{
|
9
|
-
VALUE str, io, write_len;
|
10
|
-
int write_len_i;
|
11
|
-
|
12
|
-
if (png_ptr == NULL)
|
13
|
-
return;
|
14
|
-
|
15
|
-
str = rb_str_new(data, length);
|
16
|
-
io = (VALUE)png_get_io_ptr(png_ptr);
|
17
|
-
write_len = rb_funcall(io, id_write, 1, str);
|
18
|
-
write_len_i = FIX2INT(write_len);
|
19
|
-
|
20
|
-
if ((size_t)write_len_i != length)
|
21
|
-
rb_raise(rb_eRuntimeError, "Write Error. Wrote %d instead of %d bytes.",
|
22
|
-
write_len_i, (int)length);
|
23
|
-
}
|
24
|
-
|
25
|
-
void
|
26
|
-
flush_data(png_structp png_ptr)
|
27
|
-
{
|
28
|
-
/* do nothing */
|
29
|
-
}
|
30
|
-
|
31
|
-
static VALUE
|
32
|
-
write_scanline(VALUE scan_line, VALUE *args)
|
33
|
-
{
|
34
|
-
png_structp png_ptr = (png_structp)args[1];
|
35
|
-
png_infop info_ptr = (png_infop)args[2];
|
36
|
-
png_uint_32 width;
|
37
|
-
png_byte components;
|
38
|
-
|
39
|
-
if (TYPE(scan_line) != T_STRING)
|
40
|
-
scan_line = rb_obj_as_string(scan_line);
|
41
|
-
|
42
|
-
width = png_get_image_width(png_ptr, info_ptr);
|
43
|
-
components = png_get_channels(png_ptr, info_ptr);
|
44
|
-
if ((png_uint_32)RSTRING_LEN(scan_line) != width * components)
|
45
|
-
rb_raise(rb_eRuntimeError, "Scanline has a bad size. Expected %d but got %d.",
|
46
|
-
(int)(width * components), (int)RSTRING_LEN(scan_line));
|
47
|
-
|
48
|
-
png_write_row(png_ptr, (png_bytep)RSTRING_PTR(scan_line));
|
49
|
-
return Qnil;
|
50
|
-
}
|
51
|
-
|
52
|
-
static int
|
53
|
-
id_to_color_type(ID rb, int components)
|
54
|
-
{
|
55
|
-
if (rb == id_GRAYSCALE && components == 1) return PNG_COLOR_TYPE_GRAY;
|
56
|
-
else if (rb == id_GRAYSCALE && components == 2) return PNG_COLOR_TYPE_GRAY_ALPHA;
|
57
|
-
else if (rb == id_RGB && components == 3) return PNG_COLOR_TYPE_RGB;
|
58
|
-
else if (rb == id_RGB && components == 4) return PNG_COLOR_TYPE_RGB_ALPHA;
|
59
|
-
|
60
|
-
rb_raise(rb_eRuntimeError, "Color Space not recognized.");
|
61
|
-
}
|
62
|
-
|
63
|
-
static void
|
64
|
-
size_and_colors(VALUE self, png_structp png_ptr, png_infop info_ptr)
|
65
|
-
{
|
66
|
-
VALUE image, width, height, color_model, components;
|
67
|
-
int color_type;
|
68
|
-
|
69
|
-
image = rb_funcall(self, id_image, 0);
|
70
|
-
|
71
|
-
width = rb_funcall(image, id_width, 0);
|
72
|
-
height = rb_funcall(image, id_height, 0);
|
73
|
-
components = rb_funcall(image, id_components, 0);
|
74
|
-
color_model = rb_funcall(image, id_color_model, 0);
|
75
|
-
|
76
|
-
color_type = id_to_color_type(SYM2ID(color_model), FIX2INT(components));
|
77
|
-
|
78
|
-
png_set_IHDR(png_ptr, info_ptr, FIX2INT(width), FIX2INT(height), 8,
|
79
|
-
color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
80
|
-
PNG_FILTER_TYPE_DEFAULT);
|
81
|
-
}
|
82
|
-
|
83
|
-
static VALUE
|
84
|
-
write2(VALUE *args)
|
85
|
-
{
|
86
|
-
VALUE self = args[0];
|
87
|
-
png_structp png_ptr = (png_structp)args[1];
|
88
|
-
png_infop info_ptr = (png_infop)args[2];
|
89
|
-
|
90
|
-
VALUE image = rb_funcall(self, id_image, 0);
|
91
|
-
|
92
|
-
size_and_colors(self, png_ptr, info_ptr);
|
93
|
-
|
94
|
-
png_write_info(png_ptr, info_ptr);
|
95
|
-
rb_block_call(image, id_each, 0, 0, write_scanline, (VALUE)args);
|
96
|
-
png_write_end(png_ptr, info_ptr);
|
97
|
-
|
98
|
-
return Qnil;
|
99
|
-
}
|
100
|
-
|
101
|
-
static VALUE
|
102
|
-
write2_ensure(VALUE *args)
|
103
|
-
{
|
104
|
-
png_structp png_ptr = (png_structp)args[1];
|
105
|
-
png_infop info_ptr = (png_infop)args[2];
|
106
|
-
|
107
|
-
png_destroy_write_struct(&png_ptr, &info_ptr);
|
108
|
-
return Qnil;
|
109
|
-
}
|
110
|
-
|
111
|
-
/*
|
112
|
-
* call-seq:
|
113
|
-
* writer.write(io) -> nil
|
114
|
-
*
|
115
|
-
* Compress image and write the png to io.
|
116
|
-
*/
|
117
|
-
|
118
|
-
static VALUE
|
119
|
-
pngwrite(VALUE self, VALUE io)
|
120
|
-
{
|
121
|
-
VALUE ensure_args[3];
|
122
|
-
|
123
|
-
png_structp png_ptr;
|
124
|
-
png_infop info_ptr;
|
125
|
-
|
126
|
-
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
127
|
-
(png_error_ptr)png_error_fn,
|
128
|
-
(png_error_ptr)png_warning_fn);
|
129
|
-
|
130
|
-
if (png_ptr == NULL)
|
131
|
-
rb_raise(rb_eRuntimeError, "unable to allocate a png object");
|
132
|
-
|
133
|
-
info_ptr = png_create_info_struct(png_ptr);
|
134
|
-
if (info_ptr == NULL) {
|
135
|
-
png_destroy_write_struct(&png_ptr, png_infopp_NULL);
|
136
|
-
rb_raise(rb_eRuntimeError, "unable to allocate a png info object");
|
137
|
-
}
|
138
|
-
|
139
|
-
png_set_write_fn(png_ptr, (void *)io, write_data, flush_data);
|
140
|
-
|
141
|
-
ensure_args[0] = self;
|
142
|
-
ensure_args[1] = (VALUE)png_ptr;
|
143
|
-
ensure_args[2] = (VALUE)info_ptr;
|
144
|
-
|
145
|
-
return rb_ensure(write2, (VALUE)ensure_args, write2_ensure,
|
146
|
-
(VALUE)ensure_args);
|
147
|
-
}
|
148
|
-
|
149
|
-
void
|
150
|
-
Init_png_native_writer()
|
151
|
-
{
|
152
|
-
VALUE mAxon = rb_define_module("Axon");
|
153
|
-
VALUE mNativeWriter = rb_define_module_under(mAxon, "PNGNativeWriter");
|
154
|
-
|
155
|
-
rb_define_method(mNativeWriter, "png_native_write", pngwrite, 1);
|
156
|
-
|
157
|
-
id_GRAYSCALE = rb_intern("GRAYSCALE");
|
158
|
-
id_RGB = rb_intern("RGB");
|
159
|
-
id_write = rb_intern("write");
|
160
|
-
id_image = rb_intern("image");
|
161
|
-
id_each = rb_intern("each");
|
162
|
-
id_width = rb_intern("width");
|
163
|
-
id_height = rb_intern("height");
|
164
|
-
id_color_model = rb_intern("color_model");
|
165
|
-
id_components = rb_intern("components");
|
166
|
-
}
|
data/ext/axon/png_reader.c
DELETED
@@ -1,381 +0,0 @@
|
|
1
|
-
#include "png_common.h"
|
2
|
-
|
3
|
-
static ID id_read, id_GRAYSCALE, id_RGB;
|
4
|
-
|
5
|
-
struct png_data {
|
6
|
-
png_structp png_ptr;
|
7
|
-
png_infop info_ptr;
|
8
|
-
|
9
|
-
int needs_reset;
|
10
|
-
int locked;
|
11
|
-
int rewind_after_scanlines;
|
12
|
-
|
13
|
-
VALUE io;
|
14
|
-
};
|
15
|
-
|
16
|
-
static void
|
17
|
-
raise_if_locked(struct png_data *reader)
|
18
|
-
{
|
19
|
-
if (reader->locked)
|
20
|
-
rb_raise(rb_eRuntimeError, "Can't modify a locked Reader");
|
21
|
-
}
|
22
|
-
|
23
|
-
static void
|
24
|
-
free_png(struct png_data *reader)
|
25
|
-
{
|
26
|
-
png_structp png_ptr;
|
27
|
-
png_infop info_ptr;
|
28
|
-
|
29
|
-
png_ptr = reader->png_ptr;
|
30
|
-
info_ptr = reader->info_ptr;
|
31
|
-
|
32
|
-
if (png_ptr && info_ptr)
|
33
|
-
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
34
|
-
else if (png_ptr)
|
35
|
-
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
36
|
-
}
|
37
|
-
|
38
|
-
static void
|
39
|
-
free_reader(struct png_data *reader)
|
40
|
-
{
|
41
|
-
free_png(reader);
|
42
|
-
free(reader);
|
43
|
-
}
|
44
|
-
|
45
|
-
void
|
46
|
-
read_data_fn(png_structp png_ptr, png_bytep data, png_size_t length)
|
47
|
-
{
|
48
|
-
VALUE io, str;
|
49
|
-
size_t read_len;
|
50
|
-
|
51
|
-
if (png_ptr == NULL)
|
52
|
-
return;
|
53
|
-
|
54
|
-
io = (VALUE)png_get_io_ptr(png_ptr);
|
55
|
-
str = rb_funcall(io, id_read, 1, INT2FIX(length));
|
56
|
-
|
57
|
-
if (NIL_P(str))
|
58
|
-
rb_raise(rb_eRuntimeError, "Read Error. Reader returned nil.");
|
59
|
-
|
60
|
-
StringValue(str);
|
61
|
-
read_len = RSTRING_LEN(str);
|
62
|
-
|
63
|
-
if (read_len != length)
|
64
|
-
rb_raise(rb_eRuntimeError, "Read Error. Read %d instead of %d bytes.",
|
65
|
-
(int)read_len, (int)length);
|
66
|
-
|
67
|
-
png_memcpy(data, RSTRING_PTR(str), read_len);
|
68
|
-
}
|
69
|
-
|
70
|
-
static void
|
71
|
-
mark(struct png_data *reader)
|
72
|
-
{
|
73
|
-
VALUE io = reader->io;
|
74
|
-
|
75
|
-
if (io)
|
76
|
-
rb_gc_mark(io);
|
77
|
-
}
|
78
|
-
|
79
|
-
static void
|
80
|
-
allocate_png(struct png_data *reader)
|
81
|
-
{
|
82
|
-
png_structp png_ptr;
|
83
|
-
png_infop info_ptr;
|
84
|
-
|
85
|
-
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
|
86
|
-
(png_error_ptr)png_error_fn,
|
87
|
-
(png_error_ptr)png_warning_fn);
|
88
|
-
|
89
|
-
if (png_ptr == NULL)
|
90
|
-
rb_raise(rb_eRuntimeError, "unable to allocate a png object");
|
91
|
-
|
92
|
-
info_ptr = png_create_info_struct(png_ptr);
|
93
|
-
if (info_ptr == NULL) {
|
94
|
-
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
95
|
-
rb_raise(rb_eRuntimeError, "unable to allocate a png info object");
|
96
|
-
}
|
97
|
-
|
98
|
-
reader->png_ptr = png_ptr;
|
99
|
-
reader->info_ptr = info_ptr;
|
100
|
-
}
|
101
|
-
|
102
|
-
static VALUE
|
103
|
-
allocate(VALUE klass)
|
104
|
-
{
|
105
|
-
VALUE self;
|
106
|
-
struct png_data *reader;
|
107
|
-
|
108
|
-
self = Data_Make_Struct(klass, struct png_data, mark, free_reader, reader);
|
109
|
-
allocate_png(reader);
|
110
|
-
|
111
|
-
return self;
|
112
|
-
}
|
113
|
-
|
114
|
-
VALUE
|
115
|
-
read_info(struct png_data *reader)
|
116
|
-
{
|
117
|
-
png_structp png_ptr;
|
118
|
-
png_infop info_ptr;
|
119
|
-
|
120
|
-
png_ptr = reader->png_ptr;
|
121
|
-
info_ptr = reader->info_ptr;
|
122
|
-
png_read_info(png_ptr, info_ptr);
|
123
|
-
|
124
|
-
return Qnil;
|
125
|
-
}
|
126
|
-
|
127
|
-
/*
|
128
|
-
* call-seq:
|
129
|
-
* Reader.new(string_or_io[, markers]) -> reader
|
130
|
-
*
|
131
|
-
* Create a new JPEG Reader. string_or_io may be a String or any object that
|
132
|
-
* responds to read and close.
|
133
|
-
*
|
134
|
-
* markers should be an array of valid JPEG header marker symbols. Valid
|
135
|
-
* symbols are :APP0 through :APP15 and :COM.
|
136
|
-
*
|
137
|
-
* If performance is important, you can avoid reading all header markers by
|
138
|
-
* supplying an empty array, [].
|
139
|
-
*
|
140
|
-
* When markers are not specified, we read all known JPEG markers.
|
141
|
-
*/
|
142
|
-
static VALUE
|
143
|
-
initialize(VALUE self, VALUE io)
|
144
|
-
{
|
145
|
-
struct png_data *reader;
|
146
|
-
|
147
|
-
Data_Get_Struct(self, struct png_data, reader);
|
148
|
-
raise_if_locked(reader);
|
149
|
-
png_set_read_fn(reader->png_ptr, (void *)io, read_data_fn);
|
150
|
-
reader->io = io;
|
151
|
-
read_info(reader);
|
152
|
-
|
153
|
-
return self;
|
154
|
-
}
|
155
|
-
|
156
|
-
static int
|
157
|
-
get_components(png_structp png_ptr, png_infop info_ptr)
|
158
|
-
{
|
159
|
-
switch (png_get_color_type(png_ptr, info_ptr)) {
|
160
|
-
case PNG_COLOR_TYPE_GRAY: return 1;
|
161
|
-
case PNG_COLOR_TYPE_GRAY_ALPHA: return 2;
|
162
|
-
case PNG_COLOR_TYPE_RGB: return 3;
|
163
|
-
case PNG_COLOR_TYPE_RGB_ALPHA: return 4;
|
164
|
-
}
|
165
|
-
|
166
|
-
return 0;
|
167
|
-
}
|
168
|
-
|
169
|
-
/*
|
170
|
-
* call-seq:
|
171
|
-
* reader.num_components -> number
|
172
|
-
*
|
173
|
-
* Retrieve the number of components as stored in the JPEG image.
|
174
|
-
*/
|
175
|
-
static VALUE
|
176
|
-
components(VALUE self)
|
177
|
-
{
|
178
|
-
struct png_data *reader;
|
179
|
-
png_structp png_ptr;
|
180
|
-
png_infop info_ptr;
|
181
|
-
int c;
|
182
|
-
|
183
|
-
Data_Get_Struct(self, struct png_data, reader);
|
184
|
-
png_ptr = reader->png_ptr;
|
185
|
-
info_ptr = reader->info_ptr;
|
186
|
-
|
187
|
-
c = get_components(png_ptr, info_ptr);
|
188
|
-
|
189
|
-
if (c == 0)
|
190
|
-
return Qnil;
|
191
|
-
|
192
|
-
return INT2FIX(c);
|
193
|
-
}
|
194
|
-
|
195
|
-
static ID
|
196
|
-
png_color_type_to_id(png_byte color_type)
|
197
|
-
{
|
198
|
-
switch (color_type) {
|
199
|
-
case PNG_COLOR_TYPE_GRAY: return id_GRAYSCALE;
|
200
|
-
case PNG_COLOR_TYPE_GRAY_ALPHA: return id_GRAYSCALE;
|
201
|
-
case PNG_COLOR_TYPE_RGB: return id_RGB;
|
202
|
-
case PNG_COLOR_TYPE_RGB_ALPHA: return id_RGB;
|
203
|
-
}
|
204
|
-
|
205
|
-
rb_raise(rb_eRuntimeError, "PNG Color Type not recognized.");
|
206
|
-
}
|
207
|
-
|
208
|
-
/*
|
209
|
-
* call-seq:
|
210
|
-
* reader.color_model -> symbol
|
211
|
-
*
|
212
|
-
* Returns a symbol representing the color space into which the JPEG will be
|
213
|
-
* transformed as it is read.
|
214
|
-
*
|
215
|
-
* By default this color space is based on Reader#color_space.
|
216
|
-
*
|
217
|
-
* Possible color spaces are: GRAYSCALE, RGB, YCbCr, CMYK, and YCCK. This method
|
218
|
-
* will return nil if the color space is not recognized.
|
219
|
-
*/
|
220
|
-
static VALUE
|
221
|
-
color_model(VALUE self)
|
222
|
-
{
|
223
|
-
struct png_data *reader;
|
224
|
-
png_structp png_ptr;
|
225
|
-
png_infop info_ptr;
|
226
|
-
|
227
|
-
Data_Get_Struct(self, struct png_data, reader);
|
228
|
-
png_ptr = reader->png_ptr;
|
229
|
-
info_ptr = reader->info_ptr;
|
230
|
-
|
231
|
-
return ID2SYM(png_color_type_to_id(png_get_color_type(png_ptr, info_ptr)));
|
232
|
-
}
|
233
|
-
|
234
|
-
static VALUE
|
235
|
-
each2(VALUE arg)
|
236
|
-
{
|
237
|
-
struct png_data *reader;
|
238
|
-
png_structp png_ptr;
|
239
|
-
png_infop info_ptr;
|
240
|
-
int i, width, height, components, sl_width;
|
241
|
-
VALUE sl;
|
242
|
-
|
243
|
-
reader = (struct png_data *)arg;
|
244
|
-
png_ptr = reader->png_ptr;
|
245
|
-
info_ptr = reader->info_ptr;
|
246
|
-
|
247
|
-
width = png_get_image_width(png_ptr, info_ptr);
|
248
|
-
height = png_get_image_height(png_ptr, info_ptr);
|
249
|
-
components = get_components(png_ptr, info_ptr);
|
250
|
-
sl_width = width * components;
|
251
|
-
|
252
|
-
for (i = 0; i < height; i++) {
|
253
|
-
sl = rb_str_new(0, sl_width);
|
254
|
-
png_read_row(png_ptr, (png_bytep)RSTRING_PTR(sl), png_bytep_NULL);
|
255
|
-
|
256
|
-
if (rb_block_given_p())
|
257
|
-
rb_yield(sl);
|
258
|
-
}
|
259
|
-
|
260
|
-
return Qnil;
|
261
|
-
}
|
262
|
-
|
263
|
-
static VALUE
|
264
|
-
each2_ensure(VALUE arg)
|
265
|
-
{
|
266
|
-
struct png_data *reader;
|
267
|
-
|
268
|
-
reader = (struct png_data *)arg;
|
269
|
-
reader->locked = 0;
|
270
|
-
reader->needs_reset = 1;
|
271
|
-
|
272
|
-
return Qnil;
|
273
|
-
}
|
274
|
-
|
275
|
-
static void
|
276
|
-
reset_reader(struct png_data *reader)
|
277
|
-
{
|
278
|
-
VALUE io;
|
279
|
-
|
280
|
-
io = reader->io;
|
281
|
-
free_png(reader);
|
282
|
-
allocate_png(reader);
|
283
|
-
png_set_read_fn(reader->png_ptr, (void *)io, read_data_fn);
|
284
|
-
reader->io = io;
|
285
|
-
read_info(reader);
|
286
|
-
}
|
287
|
-
|
288
|
-
/*
|
289
|
-
* call-seq:
|
290
|
-
* reader.each(&block)
|
291
|
-
*
|
292
|
-
* Iterate over each decoded scanline in the JPEG image.
|
293
|
-
*/
|
294
|
-
static VALUE
|
295
|
-
each(VALUE self)
|
296
|
-
{
|
297
|
-
struct png_data *reader;
|
298
|
-
|
299
|
-
Data_Get_Struct(self, struct png_data, reader);
|
300
|
-
|
301
|
-
if (reader->needs_reset)
|
302
|
-
reset_reader(reader);
|
303
|
-
|
304
|
-
raise_if_locked(reader);
|
305
|
-
reader->locked = 1;
|
306
|
-
rb_ensure(each2, (VALUE)reader, each2_ensure, (VALUE)reader);
|
307
|
-
|
308
|
-
return Qnil;
|
309
|
-
}
|
310
|
-
|
311
|
-
/*
|
312
|
-
* call-seq:
|
313
|
-
* reader.width -> number
|
314
|
-
*
|
315
|
-
* Retrieve the width of the image as it will be written out. This is primarily
|
316
|
-
* affected by scale_num and scale_denom if they are set.
|
317
|
-
*
|
318
|
-
* Note that this value is not automatically calculated unless you call
|
319
|
-
* Reader#calc_output_dimensions or after Reader#each_scanline has been called.
|
320
|
-
*/
|
321
|
-
static VALUE
|
322
|
-
width(VALUE self)
|
323
|
-
{
|
324
|
-
struct png_data *reader;
|
325
|
-
png_structp png_ptr;
|
326
|
-
png_infop info_ptr;
|
327
|
-
|
328
|
-
Data_Get_Struct(self, struct png_data, reader);
|
329
|
-
png_ptr = reader->png_ptr;
|
330
|
-
info_ptr = reader->info_ptr;
|
331
|
-
|
332
|
-
return INT2FIX(png_get_image_width(png_ptr, info_ptr));
|
333
|
-
}
|
334
|
-
|
335
|
-
/*
|
336
|
-
* call-seq:
|
337
|
-
* reader.height -> number
|
338
|
-
*
|
339
|
-
* Retrieve the height of the image as it will be written out. This is primarily
|
340
|
-
* affected by scale_num and scale_denom if they are set.
|
341
|
-
*
|
342
|
-
* Note that this value is not automatically calculated unless you call
|
343
|
-
* Reader#calc_output_dimensions or after Reader#each has been called.
|
344
|
-
*/
|
345
|
-
static VALUE
|
346
|
-
height(VALUE self)
|
347
|
-
{
|
348
|
-
struct png_data *reader;
|
349
|
-
png_structp png_ptr;
|
350
|
-
png_infop info_ptr;
|
351
|
-
|
352
|
-
Data_Get_Struct(self, struct png_data, reader);
|
353
|
-
png_ptr = reader->png_ptr;
|
354
|
-
info_ptr = reader->info_ptr;
|
355
|
-
|
356
|
-
return INT2FIX(png_get_image_height(png_ptr, info_ptr));
|
357
|
-
}
|
358
|
-
|
359
|
-
void
|
360
|
-
Init_png_reader()
|
361
|
-
{
|
362
|
-
VALUE mAxon = rb_define_module("Axon");
|
363
|
-
VALUE cPNGReader = rb_define_class_under(mAxon, "PNGReader", rb_cObject);
|
364
|
-
VALUE mImage = rb_define_module_under(mAxon, "Image");
|
365
|
-
|
366
|
-
rb_include_module(cPNGReader, mImage);
|
367
|
-
rb_include_module(cPNGReader, rb_mEnumerable);
|
368
|
-
|
369
|
-
rb_define_alloc_func(cPNGReader, allocate);
|
370
|
-
|
371
|
-
rb_define_method(cPNGReader, "initialize", initialize, 1);
|
372
|
-
rb_define_method(cPNGReader, "color_model", color_model, 0);
|
373
|
-
rb_define_method(cPNGReader, "components", components, 0);
|
374
|
-
rb_define_method(cPNGReader, "width", width, 0);
|
375
|
-
rb_define_method(cPNGReader, "height", height, 0);
|
376
|
-
rb_define_method(cPNGReader, "each", each, 0);
|
377
|
-
|
378
|
-
id_read = rb_intern("read");
|
379
|
-
id_GRAYSCALE = rb_intern("GRAYSCALE");
|
380
|
-
id_RGB = rb_intern("RGB");
|
381
|
-
}
|