axon 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }