/* * Copyright (C) 2014 Andreas Maier, Christian Jaremenko * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.conrad.io; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import edu.stanford.rsl.conrad.data.numeric.Grid2D; import edu.stanford.rsl.conrad.utils.CONRAD; import ij.IJ; import ij.io.FileInfo; /** * Class to stream Cellvizio's MTK Format. * * @author akmaier * */ public class MKTProjectionSource extends FileProjectionSource { protected boolean debug = true; private boolean directoryMode; private ArrayList<File> fileList; @Override public void initStream (String filename) throws IOException { File file = new File(filename); if (file.isDirectory()){ // multi file format fileList = new ArrayList<File>(); String [] files = file.list(); Arrays.sort(files); for (String f: files){ if (f.substring(f.length()-4).compareToIgnoreCase(".mkt")==0){ fileList.add(new File(file.getAbsolutePath() + "/" +f)); } } if (fileList.size() == 0) throw new IOException("Directory does not contain .viv files"); fi = getHeaderInfo(fileList.get(0).getAbsolutePath()); directoryMode = true; } else { // Code for single file fi = getHeaderInfo(filename); } init(); } /** * Reads the header information from the file into a fileinfo object * @param filename the filename * @return the FileInfo * @throws IOException */ public FileInfo getHeaderInfo( String filename ) throws IOException { if (IJ.debugMode) CONRAD.log("Entering MKT_Reader.getHeaderInfo():"); FileInfo fi = new FileInfo(); File file = new File(filename); fi.fileName=file.getName(); fi.directory = file.getParent() + "/"; // NB Need RAF in order to ensure that we know file offset fi.fileType = FileInfo.GRAY16_SIGNED; // just assume this for the mo fi.fileFormat = FileInfo.RAW; fi.nImages = 1; // read header info FileInputStream fis = new FileInputStream(file); byte [] unknownHeader = new byte[10]; byte [] size = new byte[4]; fis.read(unknownHeader); fis.read(size); long sizeInByte = ByteBuffer.wrap(size).getInt(); fis.close(); fi.offset = 16; fi.gapBetweenImages=32; //System.out.println("Read " + fi.offset); if (fi.offset != 16){ throw new IOException("Wrong Header Size; Not an MKT File."); } fi.width = 576; if((sizeInByte/(2*fi.width))%2!=0){ fi.width=512; fi.height = (int) (sizeInByte/(2*fi.width)); } else { fi.height = (int) (sizeInByte/(2*fi.width)); } /* Here we had a look at the 16 byte header and this is what we found so far: * Width Height Size Size (Byte) Found Size B Hex * 576 580 334080 668160 320A A3200 * 576 578 332928 665856 290A A2900 * 576 576 331776 663552 200A A2000 * 512 512 262144 524288 0008 80000 */ fi.nImages = 1204; if (true) { System.out.println("MTK Reading image with " + fi.nImages + " frames with " + fi.width + "x" + fi.height + " resolution"); } fi.compression = FileInfo.COMPRESSION_NONE; fi.intelByteOrder = true; return (fi); } private Grid2D readSingleImage(){ Grid2D revan = super.getNextProjection(); if (revan != null) { try { Thread.sleep(CONRAD.INPUT_QUEUE_DELAY); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Grid2D uncompressed = new Grid2D(revan.getWidth(), revan.getHeight()); // uncompression int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; for (int i = 0; i< revan.getWidth(); i++){ for (int j = 0; j< revan.getHeight(); j++){ int val = (int) (revan.getPixelValue(i, j)); if (val > max) max = val; if (val < min) min = val; uncompressed.putPixelValue(i,j,val); } } //System.out.println("Range: " + min + " " + max); return uncompressed; } else { return null; } } @Override public Grid2D getNextProjection(){ if (!directoryMode) { return readSingleImage(); } else { try{ fi = getHeaderInfo(fileList.get(currentIndex+1).getPath()); initStack(); return readSingleImage(); } catch (IOException e) { e.printStackTrace(); return null; } catch (IndexOutOfBoundsException e){ return null; } } } public byte[] convertInt2Bytes(int value) { byte[] buf = new byte[4]; buf[3] = (byte) ((value & 0xFF000000)>>24); buf[2] = (byte) ((value & 0x00FF0000)>>16); buf[1] = (byte) ((value & 0x0000FF00)>>8); buf[0] = (byte) (value & 0x000000FF); return buf; } public byte[] convertInt2UnShort(int value) { byte[] buf = new byte[2]; buf[1] = (byte) ((value & 0x0000FF00)>>8); buf[0] = (byte) (value & 0x000000FF); return buf; } }