axon 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -0
- data/README.rdoc +23 -49
- data/Rakefile +33 -7
- data/TODO.rdoc +6 -1
- data/ext/axon/jpeg.c +32 -66
- data/ext/axon/png.c +46 -71
- data/ext/java/axon/AxonService.java +15 -0
- data/ext/java/axon/Interpolation.java +127 -0
- data/ext/java/axon/JPEG.java +119 -0
- data/ext/java/axon/JPEGReader.java +185 -0
- data/ext/java/axon/PNG.java +47 -0
- data/ext/java/axon/PNGReader.java +164 -0
- data/ext/java/axon/RubyImage.java +216 -0
- data/lib/axon.rb +93 -7
- data/lib/axon/alpha_stripper.rb +69 -0
- data/lib/axon/axon.jar +0 -0
- data/lib/axon/cropper.rb +6 -10
- data/lib/axon/fit.rb +53 -35
- data/lib/axon/generators.rb +1 -10
- data/lib/axon/scalers.rb +2 -16
- data/test/helper.rb +7 -9
- data/test/reader_tests.rb +0 -8
- data/test/test_alpha_stripper.rb +33 -0
- data/test/test_fit.rb +38 -0
- data/test/test_jpeg_reader.rb +49 -26
- data/test/test_jpeg_writer.rb +8 -0
- data/test/writer_tests.rb +51 -40
- metadata +96 -87
@@ -0,0 +1,15 @@
|
|
1
|
+
package axon;
|
2
|
+
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.runtime.load.BasicLibraryService;
|
5
|
+
|
6
|
+
public class AxonService implements BasicLibraryService {
|
7
|
+
public boolean basicLoad(Ruby runtime) {
|
8
|
+
PNG.initPNG(runtime);
|
9
|
+
PNGReader.initPNGReader(runtime);
|
10
|
+
JPEG.initJPEG(runtime);
|
11
|
+
JPEGReader.initJPEGReader(runtime);
|
12
|
+
Interpolation.initInterpolation(runtime);
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,127 @@
|
|
1
|
+
package axon;
|
2
|
+
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.RubyFixnum;
|
5
|
+
import org.jruby.RubyNumeric;
|
6
|
+
import org.jruby.RubyModule;
|
7
|
+
import org.jruby.RubyString;
|
8
|
+
import org.jruby.anno.JRubyMethod;
|
9
|
+
import org.jruby.runtime.ThreadContext;
|
10
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
+
import org.jruby.util.ByteList;
|
12
|
+
|
13
|
+
public class Interpolation {
|
14
|
+
@JRubyMethod(required = 5, meta = true)
|
15
|
+
public static IRubyObject bilinear(ThreadContext context, IRubyObject self,
|
16
|
+
IRubyObject[] args) {
|
17
|
+
ByteList scanline1, scanline2;
|
18
|
+
double ty;
|
19
|
+
int width, src_width, src_line_size, components;
|
20
|
+
byte[] scanline_out;
|
21
|
+
|
22
|
+
width = RubyFixnum.num2int(args[2]);
|
23
|
+
components = RubyFixnum.num2int(args[4]);
|
24
|
+
ty = RubyNumeric.num2dbl(args[3]);
|
25
|
+
|
26
|
+
scanline1 = args[0].convertToString().getByteList();
|
27
|
+
scanline2 = args[1].convertToString().getByteList();
|
28
|
+
|
29
|
+
src_line_size = scanline1.getRealSize();
|
30
|
+
|
31
|
+
src_width = src_line_size / components - 1;
|
32
|
+
|
33
|
+
scanline_out = calc_bilinear(width, src_width, components, ty,
|
34
|
+
scanline1.getUnsafeBytes(), scanline2.getUnsafeBytes());
|
35
|
+
|
36
|
+
return(new RubyString(context.getRuntime(), context.getRuntime().getString(), scanline_out));
|
37
|
+
}
|
38
|
+
|
39
|
+
private static byte[] calc_bilinear(int width, int src_width,
|
40
|
+
int components, double ty, byte[] scanline1, byte[] scanline2) {
|
41
|
+
byte[] dest_sl;
|
42
|
+
double width_ratio_inv, sample_x, tx, _tx, p00, p10, p01, p11;
|
43
|
+
int c0, c1, dest_pos, sample_x_i;
|
44
|
+
short c00, c10, c01, c11;
|
45
|
+
|
46
|
+
dest_sl = new byte[width * components];
|
47
|
+
width_ratio_inv = (double)src_width / width;
|
48
|
+
|
49
|
+
dest_pos = 0;
|
50
|
+
for (int i = 0; i < width; i++) {
|
51
|
+
sample_x = i * width_ratio_inv;
|
52
|
+
sample_x_i = (int)sample_x;
|
53
|
+
|
54
|
+
tx = sample_x - sample_x_i;
|
55
|
+
_tx = 1 - tx;
|
56
|
+
|
57
|
+
p11 = tx * ty;
|
58
|
+
p01 = _tx * ty;
|
59
|
+
p10 = tx - p11;
|
60
|
+
p00 = _tx - p01;
|
61
|
+
|
62
|
+
c0 = sample_x_i * components;
|
63
|
+
c1 = c0 + components;
|
64
|
+
|
65
|
+
for (int j = 0; j < components; j++) {
|
66
|
+
c00 = (short)(0x000000FF & (int)scanline1[c0 + j]);
|
67
|
+
c10 = (short)(0x000000FF & (int)scanline1[c1 + j]);
|
68
|
+
c01 = (short)(0x000000FF & (int)scanline2[c0 + j]);
|
69
|
+
c11 = (short)(0x000000FF & (int)scanline2[c1 + j]);
|
70
|
+
|
71
|
+
dest_sl[dest_pos] = (byte)(((short)(p00 * c00 + p10 * c10 + p01 * c01 + p11 * c11)) & 0xFF);
|
72
|
+
dest_pos += 1;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
return dest_sl;
|
77
|
+
|
78
|
+
}
|
79
|
+
|
80
|
+
@JRubyMethod(meta = true)
|
81
|
+
public static IRubyObject nearest(ThreadContext context, IRubyObject self,
|
82
|
+
IRubyObject rb_scanline,
|
83
|
+
IRubyObject rb_width,
|
84
|
+
IRubyObject rb_components) {
|
85
|
+
ByteList scanline_in;
|
86
|
+
byte[] scanline_out;
|
87
|
+
int width, src_width, src_line_size, components;
|
88
|
+
|
89
|
+
width = RubyFixnum.num2int(rb_width);
|
90
|
+
components = RubyFixnum.num2int(rb_components);
|
91
|
+
|
92
|
+
scanline_in = rb_scanline.convertToString().getByteList();
|
93
|
+
src_line_size = scanline_in.getRealSize();
|
94
|
+
|
95
|
+
src_width = src_line_size / components;
|
96
|
+
scanline_out = calc_nearest(width, src_width, components, scanline_in.getUnsafeBytes());
|
97
|
+
|
98
|
+
return(new RubyString(context.getRuntime(), context.getRuntime().getString(), scanline_out));
|
99
|
+
}
|
100
|
+
|
101
|
+
private static byte[] calc_nearest(int width, int src_width,
|
102
|
+
int components, byte[] scanline) {
|
103
|
+
double inv_scale_x;
|
104
|
+
byte[] dest_sl;
|
105
|
+
int src_pos, dest_pos, i, j;
|
106
|
+
|
107
|
+
inv_scale_x = (double)src_width / width;
|
108
|
+
dest_sl = new byte[width * components];
|
109
|
+
|
110
|
+
dest_pos = 0;
|
111
|
+
for (i = 0; i < width; i++) {
|
112
|
+
src_pos = (int)(i * inv_scale_x) * components;
|
113
|
+
for (j = 0; j < components; j++) {
|
114
|
+
dest_sl[dest_pos] = scanline[src_pos + j];
|
115
|
+
dest_pos += 1;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
return dest_sl;
|
120
|
+
}
|
121
|
+
|
122
|
+
static void initInterpolation(Ruby runtime) {
|
123
|
+
RubyModule axon = runtime.defineModule("Axon");
|
124
|
+
RubyModule interpolation = axon.defineModuleUnder("Interpolation");
|
125
|
+
interpolation.defineAnnotatedMethods(Interpolation.class);
|
126
|
+
}
|
127
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
package axon;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.util.Iterator;
|
5
|
+
|
6
|
+
import javax.imageio.ImageIO;
|
7
|
+
import javax.imageio.IIOImage;
|
8
|
+
import javax.imageio.IIOException;
|
9
|
+
import javax.imageio.ImageTypeSpecifier;
|
10
|
+
import javax.imageio.ImageWriteParam;
|
11
|
+
import javax.imageio.ImageWriter;
|
12
|
+
import javax.imageio.stream.ImageOutputStream;
|
13
|
+
|
14
|
+
import java.awt.image.ColorModel;
|
15
|
+
import java.awt.image.SampleModel;
|
16
|
+
|
17
|
+
import org.jruby.Ruby;
|
18
|
+
import org.jruby.RubyFixnum;
|
19
|
+
import org.jruby.RubyHash;
|
20
|
+
import org.jruby.RubyString;
|
21
|
+
import org.jruby.RubyModule;
|
22
|
+
import org.jruby.RubySymbol;
|
23
|
+
import org.jruby.anno.JRubyMethod;
|
24
|
+
import org.jruby.runtime.ThreadContext;
|
25
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
26
|
+
import org.jruby.util.IOOutputStream;
|
27
|
+
|
28
|
+
public class JPEG {
|
29
|
+
|
30
|
+
/*
|
31
|
+
* OpenJDK (IcedTea6 1.9.10), has an implementation of JPEGImageReader that
|
32
|
+
* loads the entire image into memory via read() before compressing it. Not
|
33
|
+
* sure why it does this -- the PNGImageReader is much nicer and only
|
34
|
+
* buffers one scanline at a time.
|
35
|
+
*
|
36
|
+
* Be warned -- large images can take up lots of memory here.
|
37
|
+
*/
|
38
|
+
|
39
|
+
@JRubyMethod(meta = true, required = 2, optional = 1)
|
40
|
+
public static IRubyObject write(ThreadContext context, IRubyObject self,
|
41
|
+
IRubyObject[] args) throws IOException {
|
42
|
+
IRubyObject img_in, ruby_io, rb_quality, rb_icc_profile;
|
43
|
+
RubyHash options;
|
44
|
+
Iterator writers;
|
45
|
+
ImageWriter writer;
|
46
|
+
IOOutputStream jruby_io;
|
47
|
+
ImageOutputStream ios;
|
48
|
+
RubyImage img;
|
49
|
+
ImageWriteParam iwp;
|
50
|
+
ImageTypeSpecifier dest_type;
|
51
|
+
ColorModel cm;
|
52
|
+
SampleModel sm;
|
53
|
+
int quality;
|
54
|
+
byte[] icc_profile;
|
55
|
+
|
56
|
+
writers = ImageIO.getImageWritersByFormatName("jpeg");
|
57
|
+
writer = (ImageWriter)writers.next();
|
58
|
+
img_in = args[0];
|
59
|
+
ruby_io = args[1];
|
60
|
+
rb_quality = null;
|
61
|
+
rb_icc_profile = null;
|
62
|
+
|
63
|
+
if (args.length > 2) {
|
64
|
+
options = (RubyHash)args[2];
|
65
|
+
rb_quality = options.fastARef(RubySymbol.newSymbol(context.getRuntime(),
|
66
|
+
"quality"));
|
67
|
+
rb_icc_profile = options.fastARef(RubySymbol.newSymbol(context.getRuntime(),
|
68
|
+
"icc_profile"));
|
69
|
+
}
|
70
|
+
|
71
|
+
jruby_io = new IOOutputStream(ruby_io, false, false);
|
72
|
+
ios = ImageIO.createImageOutputStream(jruby_io);
|
73
|
+
writer.setOutput(ios);
|
74
|
+
img = new RubyImage(img_in);
|
75
|
+
iwp = writer.getDefaultWriteParam();
|
76
|
+
|
77
|
+
if (rb_quality != null && !rb_quality.isNil()) {
|
78
|
+
quality = RubyFixnum.num2int(rb_quality);
|
79
|
+
if (quality < 1)
|
80
|
+
quality = 1;
|
81
|
+
else if (quality > 100)
|
82
|
+
quality = 100;
|
83
|
+
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
84
|
+
iwp.setCompressionQuality(quality / 100.0f);
|
85
|
+
}
|
86
|
+
|
87
|
+
/* ImageWriteParam -> ImageTypeSpecifier -> ColorModel -> ColorSpace ->
|
88
|
+
* ICC_Profile
|
89
|
+
*/
|
90
|
+
if (rb_icc_profile != null && !rb_icc_profile.isNil()) {
|
91
|
+
icc_profile = ((RubyString)rb_icc_profile).getBytes();
|
92
|
+
cm = img.getICCColorModel(icc_profile);
|
93
|
+
sm = cm.createCompatibleSampleModel(img.getWidth(), img.getHeight());
|
94
|
+
|
95
|
+
iwp.setDestinationType(new ImageTypeSpecifier(cm, sm));
|
96
|
+
// System.out.println(cs);
|
97
|
+
// iwp.setDestinationType()
|
98
|
+
}
|
99
|
+
|
100
|
+
try {
|
101
|
+
writer.write(null, new IIOImage(img, null, null), iwp);
|
102
|
+
}
|
103
|
+
catch(NegativeArraySizeException nas) {
|
104
|
+
throw context.getRuntime().newRuntimeError("An exception occurred while writing.");
|
105
|
+
}
|
106
|
+
catch(IIOException iioe) {
|
107
|
+
throw context.getRuntime().newRuntimeError("An exception occurred while writing.");
|
108
|
+
}
|
109
|
+
ios.flush();
|
110
|
+
|
111
|
+
return context.getRuntime().newFixnum(ios.getStreamPosition());
|
112
|
+
}
|
113
|
+
|
114
|
+
static void initJPEG(Ruby runtime) {
|
115
|
+
RubyModule axon = runtime.defineModule("Axon");
|
116
|
+
RubyModule jpeg = axon.defineModuleUnder("JPEG");
|
117
|
+
jpeg.defineAnnotatedMethods(JPEG.class);
|
118
|
+
}
|
119
|
+
}
|
@@ -0,0 +1,185 @@
|
|
1
|
+
package axon;
|
2
|
+
|
3
|
+
import java.awt.Rectangle;
|
4
|
+
import java.awt.color.ICC_ColorSpace;
|
5
|
+
import java.awt.image.BufferedImage;
|
6
|
+
import java.awt.image.DataBufferByte;
|
7
|
+
import java.awt.image.WritableRaster;
|
8
|
+
import java.io.IOException;
|
9
|
+
import java.io.OutputStream;
|
10
|
+
import java.io.OutputStreamWriter;
|
11
|
+
import java.io.StringWriter;
|
12
|
+
import java.util.Iterator;
|
13
|
+
|
14
|
+
import javax.imageio.ImageIO;
|
15
|
+
import javax.imageio.ImageReadParam;
|
16
|
+
import javax.imageio.ImageReader;
|
17
|
+
import javax.imageio.ImageTypeSpecifier;
|
18
|
+
import javax.imageio.metadata.IIOMetadataNode;
|
19
|
+
import javax.imageio.metadata.IIOMetadata;
|
20
|
+
import javax.imageio.stream.ImageInputStream;
|
21
|
+
|
22
|
+
import javax.xml.transform.TransformerFactory;
|
23
|
+
import javax.xml.transform.Transformer;
|
24
|
+
import javax.xml.transform.TransformerConfigurationException;
|
25
|
+
import javax.xml.transform.dom.DOMSource;
|
26
|
+
import javax.xml.transform.stream.StreamResult;
|
27
|
+
import javax.xml.transform.OutputKeys;
|
28
|
+
import javax.xml.transform.TransformerException;
|
29
|
+
|
30
|
+
import org.w3c.dom.Node;
|
31
|
+
import org.w3c.dom.Document;
|
32
|
+
|
33
|
+
import org.jruby.Ruby;
|
34
|
+
import org.jruby.RubyClass;
|
35
|
+
import org.jruby.RubyString;
|
36
|
+
import org.jruby.RubyModule;
|
37
|
+
import org.jruby.RubyObject;
|
38
|
+
import org.jruby.anno.JRubyMethod;
|
39
|
+
import org.jruby.runtime.ObjectAllocator;
|
40
|
+
import org.jruby.runtime.ThreadContext;
|
41
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
42
|
+
import org.jruby.util.IOInputStream;
|
43
|
+
|
44
|
+
public class JPEGReader extends RubyObject {
|
45
|
+
private ImageReader reader;
|
46
|
+
private IRubyObject rb_io_in;
|
47
|
+
private ImageTypeSpecifier its;
|
48
|
+
private int lineno_i;
|
49
|
+
|
50
|
+
private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
51
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
52
|
+
return new JPEGReader(runtime, klass);
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
public JPEGReader(Ruby runtime, RubyClass klass) {
|
57
|
+
super(runtime, klass);
|
58
|
+
}
|
59
|
+
|
60
|
+
@JRubyMethod
|
61
|
+
public IRubyObject initialize(IRubyObject io) {
|
62
|
+
Iterator readers;
|
63
|
+
ImageInputStream iis;
|
64
|
+
|
65
|
+
rb_io_in = io;
|
66
|
+
lineno_i = 0;
|
67
|
+
|
68
|
+
readers = ImageIO.getImageReadersByFormatName("jpeg");
|
69
|
+
reader = (ImageReader)readers.next();
|
70
|
+
|
71
|
+
try {
|
72
|
+
iis = ImageIO.createImageInputStream(new IOInputStream(rb_io_in));
|
73
|
+
}
|
74
|
+
catch(IOException ioe) {
|
75
|
+
throw getRuntime().newIOErrorFromException(ioe);
|
76
|
+
}
|
77
|
+
|
78
|
+
reader.setInput(iis, true);
|
79
|
+
|
80
|
+
try {
|
81
|
+
its = reader.getImageTypes(0).next();
|
82
|
+
}
|
83
|
+
catch(IOException ioe) {
|
84
|
+
throw getRuntime().newRuntimeError("An IO Error occured while reading.");
|
85
|
+
}
|
86
|
+
catch(ArrayIndexOutOfBoundsException oob) {
|
87
|
+
throw getRuntime().newRuntimeError("An index out of bounds error occurred while reading.");
|
88
|
+
}
|
89
|
+
|
90
|
+
return this;
|
91
|
+
}
|
92
|
+
|
93
|
+
@JRubyMethod
|
94
|
+
public IRubyObject width(ThreadContext context) {
|
95
|
+
try {
|
96
|
+
return getRuntime().newFixnum(reader.getWidth(0));
|
97
|
+
}
|
98
|
+
catch(IOException ioe) {
|
99
|
+
throw getRuntime().newIOErrorFromException(ioe);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
@JRubyMethod
|
104
|
+
public IRubyObject height(ThreadContext context) {
|
105
|
+
try {
|
106
|
+
return getRuntime().newFixnum(reader.getHeight(0));
|
107
|
+
}
|
108
|
+
catch(IOException ioe) {
|
109
|
+
throw getRuntime().newIOErrorFromException(ioe);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
@JRubyMethod
|
114
|
+
public IRubyObject components(ThreadContext context) {
|
115
|
+
try {
|
116
|
+
return getRuntime().newFixnum(getBands());
|
117
|
+
}
|
118
|
+
catch(IOException ioe) {
|
119
|
+
throw getRuntime().newIOErrorFromException(ioe);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
@JRubyMethod
|
124
|
+
public IRubyObject gets(ThreadContext context) throws IOException {
|
125
|
+
BufferedImage image;
|
126
|
+
ImageReadParam irp;
|
127
|
+
WritableRaster raster;
|
128
|
+
DataBufferByte buffer;
|
129
|
+
byte[] data;
|
130
|
+
int numbands;
|
131
|
+
byte tmp;
|
132
|
+
|
133
|
+
/* Return nil if we are already at the bottom of the image */
|
134
|
+
if (lineno_i >= reader.getHeight(0))
|
135
|
+
return(context.nil);
|
136
|
+
|
137
|
+
/* request one scanline */
|
138
|
+
irp = reader.getDefaultReadParam();
|
139
|
+
irp.setSourceRegion(new Rectangle(0, lineno_i, reader.getWidth(0), 1));
|
140
|
+
|
141
|
+
image = reader.read(0, irp);
|
142
|
+
|
143
|
+
/* get the raw bytes from the scanline */
|
144
|
+
raster = image.getRaster();
|
145
|
+
|
146
|
+
buffer = (DataBufferByte)raster.getDataBuffer();
|
147
|
+
data = buffer.getData();
|
148
|
+
|
149
|
+
/* JPEGReader forces us to reorder BGR to RGB. */
|
150
|
+
numbands = getBands();
|
151
|
+
if (numbands == 3) {
|
152
|
+
for (int i = 0; i < data.length / 3; i++) {
|
153
|
+
tmp = data[i * 3];
|
154
|
+
data[i * 3] = data[i * 3 + 2];
|
155
|
+
data[i * 3 + 2] = tmp;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
lineno_i += 1;
|
160
|
+
return(new RubyString(getRuntime(), getRuntime().getString(), data));
|
161
|
+
}
|
162
|
+
|
163
|
+
@JRubyMethod
|
164
|
+
public IRubyObject lineno(ThreadContext context) {
|
165
|
+
return getRuntime().newFixnum(lineno_i);
|
166
|
+
}
|
167
|
+
|
168
|
+
@JRubyMethod
|
169
|
+
public IRubyObject icc_profile(ThreadContext context) {
|
170
|
+
byte[] data;
|
171
|
+
data = ((ICC_ColorSpace)its.getColorModel().getColorSpace()).getProfile().getData();
|
172
|
+
return(new RubyString(getRuntime(), getRuntime().getString(), data));
|
173
|
+
}
|
174
|
+
|
175
|
+
public static void initJPEGReader(Ruby runtime) {
|
176
|
+
RubyModule axon = runtime.defineModule("Axon");
|
177
|
+
RubyModule png = axon.defineModuleUnder("JPEG");
|
178
|
+
RubyClass jpegReader = png.defineClassUnder("Reader", runtime.getObject(), ALLOCATOR);
|
179
|
+
jpegReader.defineAnnotatedMethods(JPEGReader.class);
|
180
|
+
}
|
181
|
+
|
182
|
+
private int getBands() throws IOException {
|
183
|
+
return its.getNumComponents();
|
184
|
+
}
|
185
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
package axon;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.util.Iterator;
|
5
|
+
|
6
|
+
import javax.imageio.ImageIO;
|
7
|
+
import javax.imageio.ImageWriter;
|
8
|
+
import javax.imageio.stream.ImageOutputStream;
|
9
|
+
|
10
|
+
import org.jruby.Ruby;
|
11
|
+
import org.jruby.RubyModule;
|
12
|
+
import org.jruby.anno.JRubyMethod;
|
13
|
+
import org.jruby.runtime.ThreadContext;
|
14
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
15
|
+
import org.jruby.util.IOOutputStream;
|
16
|
+
|
17
|
+
public class PNG {
|
18
|
+
@JRubyMethod(meta = true)
|
19
|
+
public static IRubyObject write(ThreadContext context, IRubyObject self,
|
20
|
+
IRubyObject img_in, IRubyObject ruby_io) throws IOException {
|
21
|
+
Iterator writers = ImageIO.getImageWritersByFormatName("png");
|
22
|
+
ImageWriter writer = (ImageWriter)writers.next();
|
23
|
+
IOOutputStream jruby_io = new IOOutputStream(ruby_io, false, false);
|
24
|
+
ImageOutputStream ios = ImageIO.createImageOutputStream(jruby_io);
|
25
|
+
writer.setOutput(ios);
|
26
|
+
RubyImage img = new RubyImage(img_in);
|
27
|
+
try {
|
28
|
+
writer.write(img);
|
29
|
+
}
|
30
|
+
catch(IllegalArgumentException iae) {
|
31
|
+
throw context.getRuntime().newRuntimeError("An Illegal Argument exception occurred while writing.");
|
32
|
+
}
|
33
|
+
catch(ArrayIndexOutOfBoundsException oob) {
|
34
|
+
throw context.getRuntime().newRuntimeError("An Out of Bounds exception occurred while writing.");
|
35
|
+
}
|
36
|
+
catch(NegativeArraySizeException nas) {
|
37
|
+
throw context.getRuntime().newRuntimeError("An exception occurred while writing.");
|
38
|
+
}
|
39
|
+
return context.getRuntime().newFixnum(ios.getStreamPosition());
|
40
|
+
}
|
41
|
+
|
42
|
+
static void initPNG(Ruby runtime) {
|
43
|
+
RubyModule axon = runtime.defineModule("Axon");
|
44
|
+
RubyModule png = axon.defineModuleUnder("PNG");
|
45
|
+
png.defineAnnotatedMethods(PNG.class);
|
46
|
+
}
|
47
|
+
}
|