Commit fb75351e authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Working on loci-compatible reader for camera files to use single-read

pass
parent 1338de2c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8,3 +8,4 @@ attic
*.log
FOCUS-PSF*
src/main/resources/trained_model
bioformats
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@
		<dependency>
			<groupId>ome</groupId>
			<artifactId>loci_tools</artifactId>
			<version>5.0.0</version>
			<version>5.9.0</version>
		</dependency>
	</dependencies>

+230 −16
Original line number Diff line number Diff line
@@ -31,24 +31,45 @@ import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import org.apache.log4j.Logger;

import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.io.FileInfo;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import loci.common.ByteArrayHandle;
import loci.common.Location;
import loci.common.RandomAccessInputStream;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory;
import loci.formats.ClassList;
import loci.formats.CoreMetadata;
import loci.formats.FormatException;
import loci.formats.IFormatReader;
import loci.formats.ImageReader;
//import loci.formats.in.TiffReader;
import loci.formats.meta.IMetadata;
import loci.formats.meta.MetadataStore;
import loci.formats.services.OMEXMLService;
import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffParser;
@@ -56,6 +77,30 @@ import loci.formats.tiff.TiffRational;
import loci.formats.tiff.TiffSaver;

public class EyesisTiff {
	  private static ClassList<IFormatReader> defaultClasses;
	  private static final Logger LOGGER = LoggerFactory.getLogger(ClassList.class);
	  public static ClassList<IFormatReader> getCustomReaderClasses() {
			defaultClasses = null;
		    if (defaultClasses == null) {
		      try {
		        defaultClasses =
		          new ClassList<IFormatReader>(
		        		  EyesisTiff.class.getClassLoader().getResource("readers.txt").getFile(), // @param file Configuration file containing the list of classes.
		        		  IFormatReader.class, // @param base Base class to which all classes are assignable.
		        		  null); // @param location Class indicating which package to search for the file.
		      }
		      catch (IOException exc) {
		        defaultClasses = new ClassList<IFormatReader>(IFormatReader.class);
		        LOGGER.info("Could not parse class list; using default classes", exc);
		      }
		    }
//		    ClassList<IFormatReader> dc = defaultClasses;
	        LOGGER.info("Loaded "+defaultClasses.getClasses().length+" classes");
		    return defaultClasses;
		  }



	//	private static org.apache.log4j.Logger log= Logger.getLogger(EyesisTiff.class);

	public EyesisTiff(){
@@ -63,6 +108,175 @@ public class EyesisTiff {


	}
	public ImagePlus readTiff(String path) {
//		TiffReader tiffReader = new TiffReader();
//		tiffReader.initFile(path);
		   // read in entire file
		// TODO: add option to get URL
		//https://docs.openmicroscopy.org/bio-formats/5.9.2/developers/in-memory.html
	    System.out.println("Reading file into memory from disk: "+path);
	    File inputFile = new File(path);
	    int fileSize = (int) inputFile.length();
	    DataInputStream in = null;
		try {
			in = new DataInputStream(new FileInputStream(inputFile));
		} catch (FileNotFoundException e) {
		    System.out.println("File not found: "+path);
		}
	    byte[] inBytes = new byte[fileSize];
	    try {
			in.readFully(inBytes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    System.out.println(fileSize + " bytes read.");

	    // determine input file suffix
	    String fileName = inputFile.getName();
	    int dot = fileName.lastIndexOf(".");
	    String suffix = dot < 0 ? "" : fileName.substring(dot);


	    // map input id string to input byte array
	    String inId = "inBytes" + suffix;
	    Location.mapFile(inId, new ByteArrayHandle(inBytes));

	 // read data from byte array using ImageReader
	    System.out.println();
	    System.out.println("Reading image data from memory...");
	    //
	    ServiceFactory factory = null;
		try {
			factory = new ServiceFactory();
		} catch (DependencyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    OMEXMLService service = null;
		try {
			service = factory.getInstance(OMEXMLService.class);
		} catch (DependencyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    IMetadata omeMeta = null;
		try {
			omeMeta = service.createOMEXMLMetadata();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

//		final Class<? extends IFormatReader>[] defaultClasses =
//				ImageReader.getDefaultReaderClasses().getClasses();
//			final int currentHash = Arrays.hashCode(defaultClasses);
//https://www.javatips.net/api/libbio-formats-java-master/components/scifio/src/loci/formats/in/BaseTiffReader.java
//https://docs.openmicroscopy.org/bio-formats/5.7.2/developers/reader-guide.html
		//https://docs.openmicroscopy.org/bio-formats/5.9.2/developers/java-library.html#file-reading-and-performance
	    ImageReader reader = new ImageReader(getCustomReaderClasses());
//		BaseTiffReader reader = new BaseTiffReader("Base_tiff_reader","tiff");
	    reader.setMetadataStore(omeMeta);
	    try {
			reader.setId(inId);
		} catch (FormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// a lot of output for each unmatched format
			//e.printStackTrace();
		}
	    /* read-end */
	    int seriesCount = reader.getSeriesCount();
	    int imageCount = reader.getImageCount();
	    int sizeX = reader.getSizeX();
	    int sizeY = reader.getSizeY();
	    int sizeZ = reader.getSizeZ();
	    int sizeC = reader.getSizeC();
	    int sizeT = reader.getSizeT();
	    int bpp =   reader.getBitsPerPixel();
	    int pixelType = reader.getPixelType();
	    java.util.List<CoreMetadata> cmd = reader.getCoreMetadataList();
	    java.util.Hashtable<java.lang.String,java.lang.Object> 	gmd = reader.getGlobalMetadata();
	    MetadataStore mtds = reader.getMetadataStore();
	    IFormatReader ifr = reader.getReader();
	    IFormatReader[] ifrs = reader.getReaders(); // all available readers?
	    // output some details
	    System.out.println("Series count: " + seriesCount);
	    System.out.println("First series:");
	    System.out.println("\tImage count = " + imageCount);
	    System.out.println("\tSizeX = " + sizeX);
	    System.out.println("\tSizeY = " + sizeY);
	    System.out.println("\tSizeZ = " + sizeZ);
	    System.out.println("\tSizeC = " + sizeC);
	    System.out.println("\tSizeT = " + sizeT);
	    System.out.println("\tbppT = " +  bpp);
	    System.out.println("\treader = " +  ifr.toString());
	    System.out.println("\tpixelType = " +  pixelType); // 3
	    byte [] bytes = null;
	    ImagePlus imp=  null;
	    try {
			bytes = reader.openBytes(0);
		} catch (FormatException e1) {
	        LOGGER.warn("Invalid image format, error "+e1);
		} catch (IOException e1) {
	        LOGGER.warn("I/O error "+e1);
		}
	    if (bytes != null) {
		    boolean is_le = reader.isLittleEndian();
		    int bytes_per_pixel =  (bpp + 7) / 9;
		    float [] pixels = new float [bytes.length/bytes_per_pixel];
		    if (bytes_per_pixel == 1) {
			    for (int i = 0; i < pixels.length; i++) {
			    	pixels[i] = ((bytes[i])) & 0xff;
			    }
		    } else {
		    	ByteBuffer bb = ByteBuffer.wrap(bytes);
		    	if (is_le) {
		    		bb.order( ByteOrder.LITTLE_ENDIAN);
		    	} else {
		    		bb.order( ByteOrder.BIG_ENDIAN);
		    	}
			    for (int i = 0; i < pixels.length; i++) {
			    	pixels[i] = ((bb.getShort())) & 0xffff;
			    }
		    }

		    ImageProcessor ip=new FloatProcessor(reader.getSizeX(), reader.getSizeY());
			ip.setPixels(pixels);
			ip.resetMinAndMax();
//			imp =  new ImagePlus(fileName, ip); // original jp46 reader had full path as title
			imp =  new ImagePlus(path, ip); // original jp46 reader had full path as title
	    }

//	    ImagePlus imp= makeArrays(pixels, width, height, title);
	    try {
			reader.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return imp;
	}

/*
 * image width 	getSizeX()
image height 	getSizeY()
number of series per file 	getSeriesCount()
total number of images per series 	getImageCount()
number of slices in the current series 	getSizeZ()
number of timepoints in the current series 	getSizeT()
number of actual channels in the current series 	getSizeC()
number of channels per image 	getRGBChannelCount()
the ordering of the images within the current series 	getDimensionOrder()
whether each image is RGB 	isRGB()
whether the pixel bytes are in little-endian order 	isLittleEndian()
whether the channels in an image are interleaved 	isInterleaved()
the type of pixel data in this file 	getPixelType()


 */

	public void savePNG_ARGB32(
			ImagePlus imp,
			String path
+103 −4
Original line number Diff line number Diff line
@@ -39,9 +39,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
@@ -66,10 +69,15 @@ import ij.gui.GUI;
import ij.gui.GenericDialog;
import ij.io.FileInfo;
import ij.io.OpenDialog;
import ij.io.Opener;
import ij.plugin.frame.PlugInFrame;
import ij.process.ImageConverter;
import ij.process.ImageProcessor;
import ij.text.TextWindow;
import loci.common.RandomAccessInputStream;
import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffParser;



@@ -1035,12 +1043,18 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
	/* Modified from Opener.java */
	ImagePlus openJpegOrGif(String dir, String name) {
		ImagePlus imp = null;
		boolean isTiff = false;
		Image img = Toolkit.getDefaultToolkit().createImage(dir+name);
		if (img!=null) {
			try {
				imp = new ImagePlus(name, img);
			} catch (IllegalStateException e) {
				return null; // error loading image
				//java.lang.IllegalStateException: Error loading image
				// Try TIFF
				Opener opener=new Opener(); // Reads Tiff images
				imp=opener.openImage("", dir+name);
				if (imp == null) return null; // error loading image
				isTiff = true;
			}

			if (imp.getType()==ImagePlus.COLOR_RGB) {
@@ -1049,15 +1063,100 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {

			IJ.showStatus("Converting to 32-bits");
			new ImageConverter(imp).convertToGray32();

			FileInfo fi = new FileInfo();
			fi.fileFormat = FileInfo.GIF_OR_JPG;
			FileInfo fi = imp.getFileInfo();
			fi.fileName = name;
			fi.directory = dir;
			fi.fileFormat = isTiff?FileInfo.TIFF: FileInfo.GIF_OR_JPG; // even if set originally, it is lost after convertToGray32
			imp.setFileInfo(fi);

			FileInfo ofi = imp.getOriginalFileInfo();
			fi = imp.getFileInfo();

// testing

			if ((ofi!=null) && (ofi.directory!=null) &&  (ofi.fileFormat ==FileInfo.TIFF)) {
				String path = ofi.directory + ofi.fileName;
				EyesisTiff ET = new EyesisTiff();
				ImagePlus imptiff = ET.readTiff(path);
				if (imptiff!=null) {
					imptiff.show();
				}

//				IJ.error("TIFF Dumper", "File path not available or not TIFF file");
				IJ.log("\\Clear");
				IJ.log("PATH = "+path);
				try {
					dumpIFDs(path);
				} catch(IOException e) {
					IJ.error("Tiff Dumper", ""+e);
				}
				Frame log = WindowManager.getFrame("Log");
				if (log!=null) log.toFront();
			}
		}


		return imp;
	}

	public static void dumpIFDs(String path) throws IOException {
		IJ.showStatus("Parsing IFDs");
		RandomAccessInputStream in = new RandomAccessInputStream(path);

		//TiffParser parser = new TiffParser(in);
		TiffParser parser = new TiffParser(in);
		IFDList ifdList = parser.getIFDs();
		IJ.showStatus("");
		for (IFD ifd : ifdList) {
			for (Integer key : ifd.keySet()) {
				int k = key.intValue();
				String name = IFD.getIFDTagName(k)+String.format("(%d [0x%x])", k,k);
				String value = prettyValue(ifd.getIFDValue(k), 0);
				IJ.log(name + " = " + value);
			}
		}
		in.close();
	}

	private static String prettyValue(Object value, int indent) {
		if (!value.getClass().isArray()) return value.toString()+" ("+value.getClass().toString()+")";
		char[] spaceChars = new char[indent];
		Arrays.fill(spaceChars, ' ');
		String spaces = new String(spaceChars);
		StringBuilder sb = new StringBuilder();
		sb.append("{\n");
		for (int i=0; i<Array.getLength(value); i++) {
			sb.append(spaces);
			sb.append(" ");
			Object component = Array.get(value, i);
			sb.append(prettyValue(component, indent + 2));
			sb.append("\n");
		}
		sb.append(spaces);
		sb.append("}");
		byte [] bstring=new byte [Array.getLength(value)];
		for (int i=0;i<bstring.length;i++) {
			try {
				bstring[i]= (byte) Integer.parseInt(Array.get(value, i).toString());
			} catch (NumberFormatException e) {
				bstring[i] = 0;
			}
		}
		//   String astring=new String((byte []) value);
		String astring="";
		try {
			astring = new String(bstring,"UTF-16");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sb.append("\n\""+astring+"\"");
		return sb.toString();
	}




	@Override
	public void setTitle (String title) {
		imageTitle=title;
+28 −0
Original line number Diff line number Diff line
/**
 **
 ** LwirCamera.java - Control/image acquisition for LWIR cameras
 ** (initially for Lepton 3.5 sensors, 103992 sesnor boards)
 **
 ** Copyright (C) 2019 Elphel, Inc.
 **
 ** -----------------------------------------------------------------------------**
 **
 **  LwirCamera.java is free software: you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ** -----------------------------------------------------------------------------**
 **
 */

public class LwirCamera {

}
Loading