Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
FileOpener.java
1 package ij.io;
2 import java.awt.*;
3 import java.awt.image.*;
4 import java.io.*;
5 import java.net.*;
6 import java.util.*;
7 import ij.gui.*;
8 import ij.process.*;
9 import ij.measure.*;
10 import ij.*;
11 
30 public class FileOpener {
31 
32  private FileInfo fi;
33  private int width, height;
34 
35  public FileOpener(FileInfo fi) {
36  this.fi = fi;
37  if (fi!=null) {
38  width = fi.width;
39  height = fi.height;
40  }
41  if (IJ.debugMode) IJ.log("FileOpener: "+fi);
42  }
43 
45  public void open() {
46  open(true);
47  }
48 
51  public ImagePlus open(boolean show) {
52  ImagePlus imp=null;
53  Object pixels;
54  ProgressBar pb=null;
55  ImageProcessor ip;
56 
57  ColorModel cm = createColorModel(fi);
58  switch (fi.fileType) {
59  case FileInfo.GRAY8:
60  case FileInfo.COLOR8:
61  case FileInfo.BITMAP:
62  pixels = readPixels(fi);
63  if (pixels==null) return null;
64  ip = new ByteProcessor(width, height, (byte[])pixels, cm);
65  imp = new ImagePlus(fi.fileName, ip);
66  break;
69  pixels = readPixels(fi);
70  if (pixels==null) return null;
71  ip = new ShortProcessor(width, height, (short[])pixels, cm);
72  imp = new ImagePlus(fi.fileName, ip);
73  break;
74  case FileInfo.GRAY32_INT:
77  pixels = readPixels(fi);
78  if (pixels==null) return null;
79  ip = new FloatProcessor(width, height, (float[])pixels, cm);
80  imp = new ImagePlus(fi.fileName, ip);
81  break;
82  case FileInfo.RGB:
83  case FileInfo.BGR:
84  case FileInfo.ARGB:
85  case FileInfo.RGB_PLANAR:
86  pixels = readPixels(fi);
87  if (pixels==null) return null;
88  ip = new ColorProcessor(width, height, (int[])pixels);
89  imp = new ImagePlus(fi.fileName, ip);
90  break;
91  }
92  imp.setFileInfo(fi);
93  setCalibration(imp);
94  if (show) imp.show();
95  IJ.showProgress(1.0);
96  return imp;
97  }
98 
100  public void revertToSaved(ImagePlus imp) {
101  Image img;
102  ProgressBar pb = IJ.getInstance().getProgressBar();
103  ImageProcessor ip;
104 
105  if (fi.fileFormat==fi.GIF_OR_JPG) {
106  // restore gif or jpg
107  img = Toolkit.getDefaultToolkit().getImage(fi.directory + fi.fileName);
108  imp.setImage(img);
109  if (imp.getType()==ImagePlus.COLOR_RGB)
111  return;
112  }
113 
114  if (fi.fileFormat==fi.DICOM) {
115  // restore DICOM
116  ImagePlus imp2 = (ImagePlus)IJ.runPlugIn("ij.plugin.DICOM", fi.directory + fi.fileName);
117  if (imp2!=null)
118  imp.setProcessor(null, imp2.getProcessor());
119  return;
120  }
121 
122  if (fi.fileFormat==fi.BMP) {
123  // restore BMP
124  ImagePlus imp2 = (ImagePlus)IJ.runPlugIn("ij.plugin.BMP_Reader", fi.directory + fi.fileName);
125  if (imp2!=null)
126  imp.setProcessor(null, imp2.getProcessor());
127  return;
128  }
129 
130  if (fi.nImages>1)
131  return;
132 
133  ColorModel cm;
134  if (fi.url==null || fi.url.equals(""))
135  IJ.showStatus("Loading: " + fi.directory + fi.fileName);
136  else
137  IJ.showStatus("Loading: " + fi.url + fi.fileName);
138  Object pixels = readPixels(fi);
139  if (pixels==null) return;
140  cm = createColorModel(fi);
141  switch (fi.fileType) {
142  case FileInfo.GRAY8:
143  case FileInfo.COLOR8:
144  case FileInfo.BITMAP:
145  ip = new ByteProcessor(width, height, (byte[])pixels, cm);
146  imp.setProcessor(null, ip);
147  break;
148  case FileInfo.GRAY16_SIGNED:
150  ip = new ShortProcessor(width, height, (short[])pixels, cm);
151  imp.setProcessor(null, ip);
152  break;
153  case FileInfo.GRAY32_INT:
154  case FileInfo.GRAY32_FLOAT:
155  ip = new FloatProcessor(width, height, (float[])pixels, cm);
156  imp.setProcessor(null, ip);
157  break;
158  case FileInfo.RGB:
159  case FileInfo.BGR:
160  case FileInfo.ARGB:
161  case FileInfo.RGB_PLANAR:
162  img = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, (int[])pixels, 0, width));
163  imp.setImage(img);
164  break;
165  }
166  }
167 
168  void setCalibration(ImagePlus imp) {
169  Calibration cal = imp.getCalibration();
170  if (fi.fileType==FileInfo.GRAY16_SIGNED) {
171  if (IJ.debugMode) IJ.log("16-bit signed");
172  double[] coeff = new double[2];
173  coeff[0] = -32768.0;
174  coeff[1] = 1.0;
175  cal.setFunction(Calibration.STRAIGHT_LINE, coeff, "gray value");
176  }
177 
178  Properties props = decodeDescriptionString();
179 
180  if (fi.pixelWidth>0.0 && fi.unit!=null) {
181  cal.pixelWidth = fi.pixelWidth;
182  cal.pixelHeight = fi.pixelHeight;
183  cal.pixelDepth = fi.pixelDepth;
184  cal.setUnit(fi.unit);
185  }
186 
187  if (fi.valueUnit!=null) {
188  int f = fi.calibrationFunction;
189  if ((f>=Calibration.STRAIGHT_LINE && f<=Calibration.LOG2 && fi.coefficients!=null)
190  ||f==Calibration.UNCALIBRATED_OD)
191  cal.setFunction(f, fi.coefficients, fi.valueUnit);
192  }
193 
194  if (fi.frameInterval!=0.0)
195  cal.frameInterval = fi.frameInterval;
196 
197  if (props==null)
198  return;
199 
200  cal.xOrigin = getDouble(props,"xorigin");
201  cal.yOrigin = getDouble(props,"yorigin");
202  cal.zOrigin = getDouble(props,"zorigin");
203  cal.info = props.getProperty("info");
204 
205  double displayMin = getDouble(props,"min");
206  double displayMax = getDouble(props,"max");
207  if (!(displayMin==0.0&&displayMax==0.0)) {
208  int type = imp.getType();
209  ImageProcessor ip = imp.getProcessor();
210  if (type==ImagePlus.GRAY8 || type==ImagePlus.COLOR_256)
211  ip.setMinAndMax(displayMin, displayMax);
212  else if (type==ImagePlus.GRAY16 || type==ImagePlus.GRAY32) {
213  if (ip.getMin()!=displayMin || ip.getMax()!=displayMax)
214  ip.setMinAndMax(displayMin, displayMax);
215  }
216  }
217  }
218 
220  public ColorModel createColorModel(FileInfo fi) {
221  if (fi.fileType==FileInfo.COLOR8 && fi.lutSize>0)
222  return new IndexColorModel(8, fi.lutSize, fi.reds, fi.greens, fi.blues);
223  else
224  return LookUpTable.createGrayscaleColorModel(fi.whiteIsZero);
225  }
226 
228  public InputStream createInputStream(FileInfo fi) throws IOException, MalformedURLException {
229  if (fi.inputStream!=null)
230  return fi.inputStream;
231  else if (fi.url!=null && !fi.url.equals(""))
232  return new URL(fi.url+fi.fileName).openStream();
233  else {
234  if (fi.directory.length()>0 && !fi.directory.endsWith(Prefs.separator))
235  fi.directory += Prefs.separator;
236  File f = new File(fi.directory + fi.fileName);
237  if (f==null || f.isDirectory() || !validateFileInfo(f, fi))
238  return null;
239  else
240  return new FileInputStream(f);
241  }
242  }
243 
244  static boolean validateFileInfo(File f, FileInfo fi) {
245  long offset = fi.longOffset>0?fi.longOffset:fi.offset;
246  long length = 0;
247  if (fi.width<=0 || fi.height<0) {
248  error("Width or height <= 0.", fi, offset, length);
249  return false;
250  }
251  if (offset>=0 && offset<1000)
252  return true;
253  if (offset<0) {
254  error("Offset is negative.", fi, offset, length);
255  return false;
256  }
257  if (fi.fileType==FileInfo.BITMAP)
258  return true;
259  length = f.length();
260  long size = fi.width*fi.height*fi.getBytesPerPixel();
261  size = fi.nImages>1?size:size/4;
262  if (fi.height==1) size = 0; // allows plugins to read info of unknown length at end of file
263  if (offset+size>length) {
264  error("Offset + image size > file length.", fi, offset, length);
265  return false;
266  }
267  return true;
268  }
269 
270  static void error(String msg, FileInfo fi, long offset, long length) {
271  IJ.showMessage("FileOpener", "FileInfo parameter error. \n"
272  +msg + "\n \n"
273  +" Width: " + fi.width + "\n"
274  +" Height: " + fi.height + "\n"
275  +" Offset: " + offset + "\n"
276  +" Bytes/pixel: " + fi.getBytesPerPixel() + "\n"
277  +(length>0?" File length: " + length + "\n":"")
278  );
279  }
280 
281 
283  Object readPixels(FileInfo fi) {
284  Object pixels = null;
285  try {
286  InputStream is = createInputStream(fi);
287  if (is==null)
288  return null;
289  ImageReader reader = new ImageReader(fi);
290  pixels = reader.readPixels(is);
291  is.close();
292  }
293  catch (Exception e) {
294  IJ.log("FileOpener.readPixels(): " + e);
295  }
296  return pixels;
297  }
298 
299  public Properties decodeDescriptionString() {
300  if (fi.description==null || fi.description.length()<7)
301  return null;
302  if (IJ.debugMode)
303  IJ.log("Image Description: " + new String(fi.description).replace('\n',' '));
304  if (!fi.description.startsWith("ImageJ"))
305  return null;
306  Properties props = new Properties();
307  InputStream is = new ByteArrayInputStream(fi.description.getBytes());
308  try {props.load(is); is.close();}
309  catch (IOException e) {return null;}
310  fi.unit = props.getProperty("unit","");
311  Double n = getNumber(props,"cf");
312  if (n!=null) fi.calibrationFunction = n.intValue();
313  double c[] = new double[5];
314  int count = 0;
315  for (int i=0; i<5; i++) {
316  n = getNumber(props,"c"+i);
317  if (n==null) break;
318  c[i] = n.doubleValue();
319  count++;
320  }
321  if (count>=2) {
322  fi.coefficients = new double[count];
323  for (int i=0; i<count; i++)
324  fi.coefficients[i] = c[i];
325  }
326  fi.valueUnit = props.getProperty("vunit");
327  n = getNumber(props,"images");
328  if (n!=null && n.doubleValue()>1.0)
329  fi.nImages = (int)n.doubleValue();
330  if (fi.nImages>1) {
331  double spacing = getDouble(props,"spacing");
332  if (spacing!=0.0)
333  fi.pixelDepth = spacing;
334  n = getNumber(props,"fps");
335  double fps = getDouble(props,"fps");
336  if (fps!=0.0)
337  fi.frameInterval = 1.0/fps;
338  }
339  return props;
340  }
341 
342  private Double getNumber(Properties props, String key) {
343  String s = props.getProperty(key);
344  if (s!=null) {
345  try {
346  return Double.valueOf(s);
347  } catch (NumberFormatException e) {}
348  }
349  return null;
350  }
351 
352  private double getDouble(Properties props, String key) {
353  Double n = getNumber(props, key);
354  return n!=null?n.doubleValue():0.0;
355  }
356 
357 
358 }