|
RoiEncoder |
|
package ij.io; import ij.gui.*; import java.awt.*; import java.io.*; import java.util.*; import java.net.*; /** Saves an ROI to a file or stream. RoiDecoder.java has a description of the file format. @see ij.io.RoiDecoder @see ij.plugin.RoiReader */ public class RoiEncoder { String path; OutputStream f; static final int HEADER_SIZE = 64; static final int VERSION = 217; final int polygon=0, rect=1, oval=2, line=3, freeline=4, polyline=5, noRoi=6, freehand=7, traced=8, angle=9, point=10; byte[] data; /** Creates an RoiEncoder using the specified path. */ public RoiEncoder(String path) { this.path = path; } /** Creates an RoiEncoder using the specified OutputStream. */ public RoiEncoder(OutputStream f) { this.f = f; } /** Save the Roi to the file of stream. */ public void write(Roi roi) throws IOException { if (f!=null) { write(roi, f); } else { f = new FileOutputStream(path); write(roi, f); f.close(); } } void write(Roi roi, OutputStream f) throws IOException { int roiType = roi.getType(); int type = rect; switch (roiType) { case Roi.POLYGON: type=polygon; break; case Roi.FREEROI: type=freehand; break; case Roi.TRACED_ROI: type=traced; break; case Roi.OVAL: type=oval; break; case Roi.LINE: type=line; break; case Roi.POLYLINE: type=polyline; break; case Roi.FREELINE: type=freeline; break; case Roi.ANGLE: type=angle; break; case Roi.COMPOSITE: type=rect; break;// shape array size (36-39) will be >0 to indicate composite type case Roi.POINT: type=point; break; default: type = rect; break; } if (roiType==Roi.COMPOSITE) { saveShapeRoi(roi, type, f); return; } int n=0; int[] x=null,y=null; if (roi instanceof PolygonRoi) { PolygonRoi p = (PolygonRoi)roi; n = p.getNCoordinates(); x = p.getXCoordinates(); y = p.getYCoordinates(); } data = new byte[HEADER_SIZE+n*4]; Rectangle r = roi.getBounds(); data[0]=73; data[1]=111; data[2]=117; data[3]=116; // "Iout" putShort(4, VERSION); data[6] = (byte)type; putShort(8, r.y); //top putShort(10, r.x); //left putShort(12, r.y+r.height); //bottom putShort(14, r.x+r.width); //right putShort(16, n); if (roi instanceof Line) { Line l = (Line)roi; putFloat(18, l.x1); putFloat(22, l.y1); putFloat(26, l.x2); putFloat(30, l.y2); } if (n>0) { int base1 = 64; int base2 = base1+2*n; for (int i=0; i<n; i++) { putShort(base1+i*2, x[i]); putShort(base2+i*2, y[i]); } } f.write(data); } void saveShapeRoi(Roi roi, int type, OutputStream f) throws IOException { float[] shapeArray = ((ShapeRoi)roi).getShapeAsArray(); if (shapeArray==null) return; BufferedOutputStream bout = new BufferedOutputStream(f); Rectangle r = roi.getBounds(); data = new byte[HEADER_SIZE + shapeArray.length*4]; data[0]=73; data[1]=111; data[2]=117; data[3]=116; // "Iout" putShort(4, VERSION); data[6] = (byte)type; putShort(8, r.y); //top putShort(10, r.x); //left putShort(12, r.y+r.height); //bottom putShort(14, r.x+r.width); //right //putShort(16, n); putInt(36, shapeArray.length); // non-zero segment count indicate composite type // handle the actual data: data are stored segment-wise, i.e., // the type of the segment followed by 0-6 control point coordinates. int base = 64; for (int i=0; i<shapeArray.length; i++) { putFloat(base, shapeArray[i]); base += 4; } bout.write(data,0,data.length); bout.flush(); } void putShort(int base, int v) { data[base] = (byte)(v>>>8); data[base+1] = (byte)v; } void putFloat(int base, float v) { int tmp = Float.floatToIntBits(v); data[base] = (byte)(tmp>>24); data[base+1] = (byte)(tmp>>16); data[base+2] = (byte)(tmp>>8); data[base+3] = (byte)tmp; } void putInt(int base, int i) { data[base] = (byte)(i>>24); data[base+1] = (byte)(i>>16); data[base+2] = (byte)(i>>8); data[base+3] = (byte)i; } }
|
RoiEncoder |
|