Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
RoiDecoder.java
1 package ij.io;
2 import ij.gui.*;
3 import java.io.*;
4 import java.util.*;
5 import java.net.*;
6 
7 /* ImageJ/NIH Image 64 byte ROI outline header
8  2 byte numbers are big-endian signed shorts
9 
10  0-3 "Iout"
11  4-5 version (>=217)
12  6-7 roi type
13  8-9 top
14  10-11 left
15  12-13 bottom
16  14-15 right
17  16-17 NCoordinates
18  18-33 x1,y1,x2,y2 (straight line)
19  34-35 line width (unused)
20  36-39 ShapeRoi size (type must be 1 if this value>0)
21  40-63 reserved (zero)
22  64-67 x0, y0 (polygon)
23  68-71 x1, y1
24  etc.
25 
26 */
27 
29 public class RoiDecoder {
30 
31  private final int polygon=0, rect=1, oval=2, line=3, freeline=4, polyline=5, noRoi=6, freehand=7, traced=8, angle=9;
32  private byte[] data;
33  private String path;
34 
35  public RoiDecoder(String path) {
36  this.path = path;
37  }
38 
40  public Roi getRoi() throws IOException {
41  File f = new File(path);
42  int size = (int)f.length();
43  if (size>500000)
44  throw new IOException("This is not an ImageJ ROI");
45  FileInputStream fis = new FileInputStream(path);
46  data = new byte[size];
47 
48  int total = 0;
49  while (total<size)
50  total += fis.read(data, total, size-total);
51  if (getByte(0)!=73 || getByte(1)!=111) //"Iout"
52  throw new IOException("This is not an ImageJ ROI");
53  int type = getByte(6);
54  int top= getShort(8);
55  int left = getShort(10);
56  int bottom = getShort(12);
57  int right = getShort(14);
58  int width = right-left;
59  int height = bottom-top;
60  int n = getShort(16);
61 
62  boolean isComposite = getInt(36)>0;
63  if (isComposite)
64  return getShapeRoi();
65 
66  Roi roi = null;
67  switch (type) {
68  case rect:
69  roi = new Roi(left, top, width, height);
70  break;
71  case oval:
72  roi = new OvalRoi(left, top, width, height);
73  break;
74  case line:
75  int x1 = (int)getFloat(18);
76  int y1 = (int)getFloat(22);
77  int x2 = (int)getFloat(26);
78  int y2 = (int)getFloat(30);
79  roi = new Line(x1, y1, x2, y2);
80  //IJ.write("line roi: "+x1+" "+y1+" "+x2+" "+y2);
81  break;
82  case polygon: case freehand: case traced: case polyline: case freeline: case angle:
83  //IJ.write("type: "+type);
84  //IJ.write("n: "+n);
85  //IJ.write("rect: "+left+","+top+" "+width+" "+height);
86  if (n==0) break;
87  int[] x = new int[n];
88  int[] y = new int[n];
89  int base1 = 64;
90  int base2 = base1+2*n;
91  int xtmp, ytmp;
92  for (int i=0; i<n; i++) {
93  xtmp = getShort(base1+i*2);
94  if (xtmp<0) xtmp = 0;
95  ytmp = getShort(base2+i*2);
96  if (ytmp<0) ytmp = 0;
97  x[i] = left+xtmp;
98  y[i] = top+ytmp;
99  //IJ.write(i+" "+getShort(base1+i*2)+" "+getShort(base2+i*2));
100  }
101  int roiType;
102  if (type==polygon)
103  roiType = Roi.POLYGON;
104  else if (type==freehand)
105  roiType = Roi.FREEROI;
106  else if (type==traced)
107  roiType = Roi.TRACED_ROI;
108  else if (type==polyline)
109  roiType = Roi.POLYLINE;
110  else if (type==freeline)
111  roiType = Roi.FREELINE;
112  else if (type==angle)
113  roiType = Roi.ANGLE;
114  else
115  roiType = Roi.FREEROI;
116  roi = new PolygonRoi(x, y, n, roiType);
117  break;
118  default:
119  throw new IOException("Unrecognized ROI type: "+type);
120  }
121  String name = f.getName();
122  if (name.endsWith(".roi"))
123  name = name.substring(0, name.length()-4);
124  roi.setName(name);
125  return roi;
126  }
127 
128  public Roi getShapeRoi() throws IOException {
129  int type = getByte(6);
130  if (type!=rect)
131  throw new IllegalArgumentException("Invalid composite ROI type");
132  int top= getShort(8);
133  int left = getShort(10);
134  int bottom = getShort(12);
135  int right = getShort(14);
136  int width = right-left;
137  int height = bottom-top;
138  int n = getInt(36);
139 
140  ShapeRoi roi = null;
141  float[] shapeArray = new float[n];
142  int base = 64;
143  for(int i=0; i<n; i++) {
144  shapeArray[i] = getFloat(base);
145  base += 4;
146  }
147  roi = new ShapeRoi(shapeArray);
148  return roi;
149  }
150 
151  int getByte(int base) {
152  return data[base]&255;
153  }
154 
155  int getShort(int base) {
156  int b0 = data[base]&255;
157  int b1 = data[base+1]&255;
158  return (short)((b0<<8) + b1);
159  }
160 
161  int getInt(int base) {
162  int b0 = data[base]&255;
163  int b1 = data[base+1]&255;
164  int b2 = data[base+2]&255;
165  int b3 = data[base+3]&255;
166  return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
167  }
168 
169  float getFloat(int base) {
170  return Float.intBitsToFloat(getInt(base));
171  }
172 
173 }