Commit 2397e946 authored by Andrey Filippov's avatar Andrey Filippov

More on JP4+Tiff reading with bioformatrs.

parent fb75351e
...@@ -8,4 +8,5 @@ attic ...@@ -8,4 +8,5 @@ attic
*.log *.log
FOCUS-PSF* FOCUS-PSF*
src/main/resources/trained_model src/main/resources/trained_model
bioformats bioformats*.*
\ No newline at end of file metadata*.*
...@@ -88,7 +88,8 @@ ...@@ -88,7 +88,8 @@
<dependency> <dependency>
<groupId>ome</groupId> <groupId>ome</groupId>
<artifactId>loci_tools</artifactId> <artifactId>loci_tools</artifactId>
<version>5.9.0</version> <version>6.1.0-SNAPSHOT</version>
<type>java-source</type>
</dependency> </dependency>
</dependencies> </dependencies>
......
...@@ -31,21 +31,32 @@ import java.awt.image.ColorModel; ...@@ -31,21 +31,32 @@ import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt; import java.awt.image.DataBufferInt;
import java.awt.image.Raster; import java.awt.image.Raster;
import java.awt.image.WritableRaster; import java.awt.image.WritableRaster;
import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.elphel.imagej.readers.ElphelTiffReader;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
...@@ -55,20 +66,15 @@ import ij.WindowManager; ...@@ -55,20 +66,15 @@ import ij.WindowManager;
import ij.io.FileInfo; import ij.io.FileInfo;
import ij.process.FloatProcessor; import ij.process.FloatProcessor;
import ij.process.ImageProcessor; import ij.process.ImageProcessor;
import loci.common.ByteArrayHandle;
import loci.common.Location;
import loci.common.RandomAccessInputStream; import loci.common.RandomAccessInputStream;
import loci.common.services.DependencyException; import loci.common.services.DependencyException;
import loci.common.services.ServiceException; import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory; import loci.common.services.ServiceFactory;
import loci.formats.ClassList; import loci.formats.ClassList;
import loci.formats.CoreMetadata;
import loci.formats.FormatException; import loci.formats.FormatException;
import loci.formats.IFormatReader; import loci.formats.IFormatReader;
import loci.formats.ImageReader; import loci.formats.ImageReader;
//import loci.formats.in.TiffReader;
import loci.formats.meta.IMetadata; import loci.formats.meta.IMetadata;
import loci.formats.meta.MetadataStore;
import loci.formats.services.OMEXMLService; import loci.formats.services.OMEXMLService;
import loci.formats.tiff.IFD; import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList; import loci.formats.tiff.IFDList;
...@@ -86,6 +92,7 @@ public class EyesisTiff { ...@@ -86,6 +92,7 @@ public class EyesisTiff {
defaultClasses = defaultClasses =
new ClassList<IFormatReader>( new ClassList<IFormatReader>(
EyesisTiff.class.getClassLoader().getResource("readers.txt").getFile(), // @param file Configuration file containing the list of classes. EyesisTiff.class.getClassLoader().getResource("readers.txt").getFile(), // @param file Configuration file containing the list of classes.
// EyesisTiff.class.getClassLoader().getResource("readers1.txt").getFile(), // @param file Configuration file containing the list of classes.
IFormatReader.class, // @param base Base class to which all classes are assignable. IFormatReader.class, // @param base Base class to which all classes are assignable.
null); // @param location Class indicating which package to search for the file. null); // @param location Class indicating which package to search for the file.
} }
...@@ -109,43 +116,14 @@ public class EyesisTiff { ...@@ -109,43 +116,14 @@ public class EyesisTiff {
} }
public ImagePlus readTiff(String path) { public ImagePlus readTiff(String path) {
// TiffReader tiffReader = new TiffReader(); return readTiff(path, "STD_"); // null);
// 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 public ImagePlus readTiff(String path, String std ) { // std - include non-elphel properties with prefix std
String fileName = inputFile.getName();
int dot = fileName.lastIndexOf(".");
String suffix = dot < 0 ? "" : fileName.substring(dot);
String inId = null;
inId = path;
// 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; ServiceFactory factory = null;
try { try {
factory = new ServiceFactory(); factory = new ServiceFactory();
...@@ -153,6 +131,7 @@ public class EyesisTiff { ...@@ -153,6 +131,7 @@ public class EyesisTiff {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
OMEXMLService service = null; OMEXMLService service = null;
try { try {
service = factory.getInstance(OMEXMLService.class); service = factory.getInstance(OMEXMLService.class);
...@@ -160,6 +139,7 @@ public class EyesisTiff { ...@@ -160,6 +139,7 @@ public class EyesisTiff {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
IMetadata omeMeta = null; IMetadata omeMeta = null;
try { try {
omeMeta = service.createOMEXMLMetadata(); omeMeta = service.createOMEXMLMetadata();
...@@ -174,8 +154,13 @@ public class EyesisTiff { ...@@ -174,8 +154,13 @@ public class EyesisTiff {
//https://www.javatips.net/api/libbio-formats-java-master/components/scifio/src/loci/formats/in/BaseTiffReader.java //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.7.2/developers/reader-guide.html
//https://docs.openmicroscopy.org/bio-formats/5.9.2/developers/java-library.html#file-reading-and-performance //https://docs.openmicroscopy.org/bio-formats/5.9.2/developers/java-library.html#file-reading-and-performance
//defaultClasses = new ClassList<IFormatReader>(IFormatReader.class);
// ClassList<IFormatReader> cl0 = getCustomReaderClasses(); // new ClassList<IFormatReader>(IFormatReader.class);
ClassList<IFormatReader> classList = new ClassList<IFormatReader>(IFormatReader.class);
classList.addClass(com.elphel.imagej.readers.ElphelTiffReader.class);
ImageReader reader = new ImageReader(getCustomReaderClasses()); ImageReader reader = new ImageReader(getCustomReaderClasses());
// BaseTiffReader reader = new BaseTiffReader("Base_tiff_reader","tiff"); // ImageReader reader = new ImageReader(classList);
reader.setMetadataStore(omeMeta); reader.setMetadataStore(omeMeta);
try { try {
reader.setId(inId); reader.setId(inId);
...@@ -187,32 +172,10 @@ public class EyesisTiff { ...@@ -187,32 +172,10 @@ public class EyesisTiff {
//e.printStackTrace(); //e.printStackTrace();
} }
/* read-end */ /* 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 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; byte [] bytes = null;
ImagePlus imp= null; ImagePlus imp= null;
try { try {
...@@ -245,11 +208,26 @@ public class EyesisTiff { ...@@ -245,11 +208,26 @@ public class EyesisTiff {
ImageProcessor ip=new FloatProcessor(reader.getSizeX(), reader.getSizeY()); ImageProcessor ip=new FloatProcessor(reader.getSizeX(), reader.getSizeY());
ip.setPixels(pixels); ip.setPixels(pixels);
ip.resetMinAndMax(); ip.resetMinAndMax();
// imp = new ImagePlus(fileName, ip); // original jp46 reader had full path as title Hashtable<String, Object> meta_hash = reader.getGlobalMetadata();
imp = new ImagePlus(path, ip); // original jp46 reader had full path as title String prefix = ElphelTiffReader.ELPHEL_PROPERTY_PREFIX;
String imageName = path;
String imageNameKey = prefix+ElphelTiffReader.CONTENT_FILENAME;
if (meta_hash.containsKey(imageNameKey)) {
imageName = meta_hash.get(imageNameKey).toString();
}
imp = new ImagePlus(imageName, ip); // original jp46 reader had full path as title
// first - save all as properties, later - only ELPHEL_*
for (String key:meta_hash.keySet()) {
if (key.startsWith(prefix)) {
imp.setProperty(key.substring(prefix.length()), meta_hash.get(key).toString());
} else if (std != null) {
imp.setProperty(std+(key.replace(" ","_")), meta_hash.get(key).toString());
}
}
encodeProperiesToInfo(imp);
} }
// ImagePlus imp= makeArrays(pixels, width, height, title);
try { try {
reader.close(); reader.close();
} catch (IOException e) { } catch (IOException e) {
...@@ -662,4 +640,58 @@ the type of pixel data in this file getPixelType() ...@@ -662,4 +640,58 @@ the type of pixel data in this file getPixelType()
return sb.toString(); return sb.toString();
} }
// copied from JP46_Reader_camera.java
public ImagePlus encodeProperiesToInfo(ImagePlus imp){
String info="<?xml version=\"1.0\" encoding=\"UTF-8\"?><properties>";
Set<Object> jp4_set;
Properties jp4_prop;
Iterator<Object> itr;
String str;
jp4_prop=imp.getProperties();
if (jp4_prop!=null) {
jp4_set=jp4_prop.keySet();
itr=jp4_set.iterator();
while(itr.hasNext()) {
str = (String) itr.next();
// if (!str.equals("Info")) info+="<"+str+">\""+jp4_prop.getProperty(str)+"\"</"+str+">";
if (!str.equals("Info")) info+="<"+str+">"+jp4_prop.getProperty(str)+"</"+str+">";
}
}
info+="</properties>\n";
imp.setProperty("Info", info);
return imp;
}
public boolean decodeProperiesFromInfo(ImagePlus imp){
if (imp.getProperty("Info")==null) return false;
String xml= (String) imp.getProperty("Info");
DocumentBuilder db=null;
try {
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
return false;
}
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e) {
return false;
} catch (IOException e) {
return false;
}
NodeList allNodes=doc.getDocumentElement().getElementsByTagName("*");
for (int i=0;i<allNodes.getLength();i++) {
String name= allNodes.item(i).getNodeName();
String value=allNodes.item(i).getFirstChild().getNodeValue();
imp.setProperty(name, value);
}
return true;
}
} }
...@@ -59,6 +59,8 @@ import org.w3c.dom.NodeList; ...@@ -59,6 +59,8 @@ import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import ij.IJ; import ij.IJ;
import ij.ImageJ; import ij.ImageJ;
import ij.ImagePlus; import ij.ImagePlus;
...@@ -75,6 +77,7 @@ import ij.process.ImageConverter; ...@@ -75,6 +77,7 @@ import ij.process.ImageConverter;
import ij.process.ImageProcessor; import ij.process.ImageProcessor;
import ij.text.TextWindow; import ij.text.TextWindow;
import loci.common.RandomAccessInputStream; import loci.common.RandomAccessInputStream;
import loci.formats.FormatException;
import loci.formats.tiff.IFD; import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList; import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffParser; import loci.formats.tiff.TiffParser;
...@@ -96,7 +99,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -96,7 +99,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
static File dir; static File dir;
public String camera_url = "http://192.168.0.236:8081/"; public String camera_url = "http://192.168.0.36:2323/";
public String camera_img = "bimg"; public String camera_img = "bimg";
public String camera_img_new = "towp/wait/bimg"; // will always wait for the next image (repetitive acquisitions get new images) public String camera_img_new = "towp/wait/bimg"; // will always wait for the next image (repetitive acquisitions get new images)
public String camera_jp46settings = ""; public String camera_jp46settings = "";
...@@ -322,6 +325,10 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -322,6 +325,10 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
if (demux) showImage=false; if (demux) showImage=false;
double [] xtraExif=new double[1]; // ExposureTime double [] xtraExif=new double[1]; // ExposureTime
double [] lla = null; double [] lla = null;
imp = openJpegOrGif(directory, fileName);
imp.show();
if (imp != null) return imp;
try { try {
imp = openJpegOrGif(directory, fileName); imp = openJpegOrGif(directory, fileName);
if (imp == null) { if (imp == null) {
...@@ -390,7 +397,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -390,7 +397,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
String arg, String arg,
boolean scale, boolean scale,
ImagePlus imp_src, ImagePlus imp_src,
boolean showImage) { boolean showImage)
{
// ImagePlus imptiff = (new EyesisTiff()).readTiff(url);
ImagePlus imptiff = null;
try {
imptiff = (new ImagejJp4Tiff()).readTiffJp4(url);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (FormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (imptiff!=null) {
imptiff.show();
if (imptiff.getType()==ImagePlus.COLOR_RGB) {
checkGrayJpegTo32Bits(imptiff);
}
IJ.showStatus("Converting to 32-bits");
new ImageConverter(imptiff).convertToGray32();
FileInfo fi = imptiff.getFileInfo();
// fi.fileName = name;
// fi.directory = dir;
fi.fileFormat = FileInfo.TIFF;
imptiff.setFileInfo(fi);
return imptiff;
}
long[] ElphelMakerNote=null; long[] ElphelMakerNote=null;
ImagePlus imp = null; ImagePlus imp = null;
boolean reuse_imp=false; boolean reuse_imp=false;
...@@ -399,14 +434,14 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -399,14 +434,14 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
double [] xtraExif=new double[1]; // ExposureTime double [] xtraExif=new double[1]; // ExposureTime
// System.out.println("imp_src is "+((imp_src!=null)?"not ":"")+"null"); // System.out.println("imp_src is "+((imp_src!=null)?"not ":"")+"null");
try { try {
imp = openJpegOrGifUsingURL(url); imp = openJpegOrGifUsingURL(url);
if (imp == null) { if (imp == null) {
IJ.showMessage("JP46 Reader Error", "Could not open the URL: " + url + " as JPEG/JP46"); IJ.showMessage("JP46 Reader Error", "Could not open the URL: " + url + " as JPEG/JP46");
} else { } else {
if ((imp_src==null) && showImage) { if ((imp_src==null) && showImage) {
// System.out.println("show() 1"); // System.out.println("show() 1");
imp.show(); /* Shows before re-ordering*/ imp.show(); /* Shows before re-ordering*/
} }
/// get rid of the "/towp/wait" if any - there is a chance to re-read the same image /// get rid of the "/towp/wait" if any - there is a chance to re-read the same image
...@@ -429,7 +464,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -429,7 +464,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
if (reuse_imp) { if (reuse_imp) {
imp=imp_src; imp=imp_src;
} else if ((imp_src!=null) && showImage) { /* tried to reuse, but wrong size */ } else if ((imp_src!=null) && showImage) { /* tried to reuse, but wrong size */
// System.out.println("show() 2"); // System.out.println("show() 2");
imp.show(); /* never did that before */ imp.show(); /* never did that before */
} }
if ((xtraExif!=null) && !Double.isNaN(xtraExif[0])){ if ((xtraExif!=null) && !Double.isNaN(xtraExif[0])){
...@@ -1042,6 +1077,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -1042,6 +1077,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
/* Modified from Opener.java */ /* Modified from Opener.java */
ImagePlus openJpegOrGif(String dir, String name) { ImagePlus openJpegOrGif(String dir, String name) {
// Testing new readers
ImagePlus imptiff = null;
// imptiff = (new EyesisTiff()).readTiff(dir+name);
try {
imptiff = (new ImagejJp4Tiff()).readTiffJp4(dir+name);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (FormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (imptiff!=null) {
imptiff.show();
if (imptiff.getType()==ImagePlus.COLOR_RGB) {
checkGrayJpegTo32Bits(imptiff);
}
IJ.showStatus("Converting to 32-bits");
new ImageConverter(imptiff).convertToGray32();
FileInfo fi = imptiff.getFileInfo();
fi.fileName = name;
fi.directory = dir;
fi.fileFormat = FileInfo.TIFF;
imptiff.setFileInfo(fi);
return imptiff;
}
ImagePlus imp = null; ImagePlus imp = null;
boolean isTiff = false; boolean isTiff = false;
Image img = Toolkit.getDefaultToolkit().createImage(dir+name); Image img = Toolkit.getDefaultToolkit().createImage(dir+name);
...@@ -1073,8 +1137,8 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -1073,8 +1137,8 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
fi = imp.getFileInfo(); fi = imp.getFileInfo();
// testing // testing
/*
if ((ofi!=null) && (ofi.directory!=null) && (ofi.fileFormat ==FileInfo.TIFF)) { if ((ofi!=null) && (ofi.directory!=null) && (ofi.fileFormat == FileInfo.TIFF)) {
String path = ofi.directory + ofi.fileName; String path = ofi.directory + ofi.fileName;
EyesisTiff ET = new EyesisTiff(); EyesisTiff ET = new EyesisTiff();
ImagePlus imptiff = ET.readTiff(path); ImagePlus imptiff = ET.readTiff(path);
...@@ -1093,6 +1157,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener { ...@@ -1093,6 +1157,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
Frame log = WindowManager.getFrame("Log"); Frame log = WindowManager.getFrame("Log");
if (log!=null) log.toFront(); if (log!=null) log.toFront();
} }
*/
} }
......
This diff is collapsed.
...@@ -29,40 +29,26 @@ import java.util.Hashtable; ...@@ -29,40 +29,26 @@ import java.util.Hashtable;
//import ij.IJ; //import ij.IJ;
import loci.formats.FormatException; import loci.formats.FormatException;
import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffParser;
import loci.formats.tiff.TiffRational;
public class ElphelMeta { public class ElphelMeta {
private Hashtable<String, String> property_table = null; // private Hashtable<String, String> property_table = null;
public ElphelMeta (TiffParser tiffParser, boolean scale) throws FormatException, IOException {
IFDList exifIFDs = tiffParser.getExifIFDs(); public static Hashtable<String, String> getMeta (Hashtable<String, String> property_table,
long[] maker_note,
double exposure,
String date_time,
boolean scale) throws FormatException, IOException {
if (property_table == null) {
property_table = new Hashtable<String, String> (); property_table = new Hashtable<String, String> ();
long[] maker_note = null;
if (exifIFDs.size() > 0) {
IFD exifIFD = exifIFDs.get(0);
tiffParser.fillInIFD(exifIFD);
if (exifIFD.containsKey(IFD.MAKER_NOTE)) {
maker_note = (long[]) exifIFD.get(IFD.MAKER_NOTE);
}
if (exifIFD.containsKey(IFD.EXPOSURE_TIME)) {
Object exp = exifIFD.get(IFD.EXPOSURE_TIME);
if (exp instanceof TiffRational) {
TiffRational texp = (TiffRational) exp;
double d = 1.0*texp.getNumerator()/texp.getDenominator();
property_table.put("EXPOSURE", String.format("%f",d));
}
} }
if (exifIFD.containsKey(IFD.DATE_TIME_ORIGINAL)) { if (!Double.isNaN(exposure)) {
String dt = exifIFD.get(IFD.DATE_TIME_ORIGINAL).toString(); property_table.put("EXPOSURE", String.format("%f",exposure));
if (exifIFD.containsKey(IFD.SUB_SEC_TIME_ORIGINAL)) {
dt += "."+exifIFD.get(IFD.SUB_SEC_TIME_ORIGINAL).toString();
}
property_table.put("DATE_TIME", dt);
} }
if (date_time == null) {
property_table.put("DATE_TIME", date_time);
} }
if (maker_note != null) {
// copied from JP4_Reader_cam // copied from JP4_Reader_cam
// Add GPS tags when there will be images to experiment (or while reimplementing JP4 reader) // Add GPS tags when there will be images to experiment (or while reimplementing JP4 reader)
double[] gains= new double[4]; double[] gains= new double[4];
...@@ -96,7 +82,6 @@ public class ElphelMeta { ...@@ -96,7 +82,6 @@ public class ElphelMeta {
long CORING_INDEX_Y=0; long CORING_INDEX_Y=0;
long CORING_INDEX_C=0; long CORING_INDEX_C=0;
double [] satValue={255.0, 255.0, 255.0, 255.0}; double [] satValue={255.0, 255.0, 255.0, 255.0};
if (maker_note !=null) {
for (i=0;i<4;i++) { /* r,g,gb,b */ for (i=0;i<4;i++) { /* r,g,gb,b */
gains[i]= maker_note[i]/65536.0; gains[i]= maker_note[i]/65536.0;
blacks[i]=(maker_note[i+4]>>24)/256.0; blacks[i]=(maker_note[i+4]>>24)/256.0;
...@@ -193,7 +178,7 @@ public class ElphelMeta { ...@@ -193,7 +178,7 @@ public class ElphelMeta {
property_table.put("FLIPV2",FLIPV2?"1":"0"); property_table.put("FLIPV2",FLIPV2?"1":"0");
property_table.put("FLIPV3",FLIPV3?"1":"0"); property_table.put("FLIPV3",FLIPV3?"1":"0");
} }
// If there are FLIPH, FLIPV - swap gains, gammas, blacks accordingly. later the images will be also flipped // If there are FLIPH, FLIPV - swap gains, gammas, blacks accordingly. later the images will be also flipped
if (FLIPV!=0) { if (FLIPV!=0) {
swapArrayElements (gains, 1, 3); swapArrayElements (gains, 1, 3);
swapArrayElements (gains, 0, 2); swapArrayElements (gains, 0, 2);
...@@ -215,9 +200,6 @@ public class ElphelMeta { ...@@ -215,9 +200,6 @@ public class ElphelMeta {
swapArrayElements (gamma_scales,3, 2); swapArrayElements (gamma_scales,3, 2);
} }
for (i=0;i<4;i++) rgammas[i]=elphel_gamma_calc (gammas[i], blacks[i], gamma_scales[i]); for (i=0;i<4;i++) rgammas[i]=elphel_gamma_calc (gammas[i], blacks[i], gamma_scales[i]);
} else {
return; // No MakerNote, return with nothing done
}
/**adjusting gains to have the result picture in the range 0..256 */ /**adjusting gains to have the result picture in the range 0..256 */
min_gain=2.0*gains[0]; min_gain=2.0*gains[0];
for (i=0;i<4;i++) { for (i=0;i<4;i++) {
...@@ -237,7 +219,7 @@ public class ElphelMeta { ...@@ -237,7 +219,7 @@ public class ElphelMeta {
property_table.put("saturation_"+i,String.format("%f",satValue[i])); property_table.put("saturation_"+i,String.format("%f",satValue[i]));
} }
// swap satValue to match FLIPH,FLIPV again // swap satValue to match FLIPH,FLIPV again
if (FLIPV!=0) { if (FLIPV!=0) {
swapArrayElements (satValue, 1, 3); swapArrayElements (satValue, 1, 3);
swapArrayElements (satValue, 0, 2); swapArrayElements (satValue, 0, 2);
...@@ -250,19 +232,25 @@ public class ElphelMeta { ...@@ -250,19 +232,25 @@ public class ElphelMeta {
property_table.put("saturation_"+i,String.format("%f",satValue[i])); property_table.put("saturation_"+i,String.format("%f",satValue[i]));
} }
} }
public Hashtable<String, String> getPropertyTable(){
return property_table; return property_table;
} }
// public Hashtable<String, String> getPropertyTable(){
// return property_table;
// }
// -- Helper methods -- // -- Helper methods --
void swapArrayElements (double[]arr,int i, int j) { static void swapArrayElements (double[]arr,int i, int j) {
double tmp=arr[i]; double tmp=arr[i];
arr[i]=arr[j]; arr[i]=arr[j];
arr[j]=tmp; arr[j]=tmp;
} }
void swapArrayElements (long[]arr,int i, int j) { static void swapArrayElements (long[]arr,int i, int j) {
long tmp=arr[i]; long tmp=arr[i];
arr[i]=arr[j]; arr[i]=arr[j];
arr[j]=tmp; arr[j]=tmp;
...@@ -270,7 +258,7 @@ public class ElphelMeta { ...@@ -270,7 +258,7 @@ public class ElphelMeta {
/* reverses gamma calculations in the camera /* reverses gamma calculations in the camera
returns double[] table , in the range 0.0..255.996 returns double[] table , in the range 0.0..255.996
*/ */
double [] elphel_gamma_calc (double gamma, double black, long gamma_scale) { static double [] elphel_gamma_calc (double gamma, double black, long gamma_scale) {
int i; int i;
double x, black256 ,k; double x, black256 ,k;
int[] gtable = new int[257]; int[] gtable = new int[257];
......
...@@ -27,15 +27,25 @@ ...@@ -27,15 +27,25 @@
*/ */
package com.elphel.imagej.readers; package com.elphel.imagej.readers;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable; import java.util.Hashtable;
import org.apache.commons.compress.utils.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import loci.common.ByteArrayHandle;
import loci.common.Location;
import loci.formats.FormatException; import loci.formats.FormatException;
import loci.formats.in.MetadataLevel; import loci.formats.in.MetadataLevel;
import loci.formats.in.TiffReader; import loci.formats.in.TiffReader;
import loci.formats.meta.MetadataStore; import loci.formats.meta.MetadataStore;
import loci.formats.tiff.IFD;
import loci.formats.tiff.IFDList;
import loci.formats.tiff.TiffRational;
/* /*
// non-IFD tags (for internal use) // non-IFD tags (for internal use)
...@@ -72,7 +82,9 @@ IFD.java public static final int MAKER_NOTE = 37500; ...@@ -72,7 +82,9 @@ IFD.java public static final int MAKER_NOTE = 37500;
public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
// -- Constants -- // -- Constants --
public static final String ELPHEL_PROPERTY_PREFIX = "ELPHEL_"; public static final String ELPHEL_PROPERTY_PREFIX = "ELPHEL_";
public static final String CONTENT_FILENAME = "CONTENT_FILENAME";
/** Merge SubIFDs into the main IFD list. */ /** Merge SubIFDs into the main IFD list. */
// protected transient boolean mergeSubIFDs = true; // false; // protected transient boolean mergeSubIFDs = true; // false;
...@@ -89,7 +101,10 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -89,7 +101,10 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
// public static final int IMAGEJ_TAG = 50839; // public static final int IMAGEJ_TAG = 50839;
// -- Fields -- // -- Fields --
// private String inId = null; // to close Location.mapFile
private URL url = null; // save here actual URL when reading file to memory
private String content_fileName = null; // from Content-disposition
private boolean file_initialized = false;
// private String companionFile; // private String companionFile;
// private String description; // private String description;
// private String calibrationUnit; // private String calibrationUnit;
...@@ -102,12 +117,75 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -102,12 +117,75 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
/** Constructs a new Tiff reader. */ /** Constructs a new Tiff reader. */
public ElphelTiffReader() { public ElphelTiffReader() {
super(); // "Tagged Image File Format", ELPHEL_TIFF_SUFFIXES); // See if we can use TiffReader without its parent super(); // "Tagged Image File Format", ELPHEL_TIFF_SUFFIXES); // See if we can use TiffReader without its parent
mergeSubIFDs = true; // false; /// mergeSubIFDs = true; // false;
LOGGER.info("ElphelTiffReader(), after supper(), mergeSubIFDs = true;"); LOGGER.info("ElphelTiffReader(), after supper(), mergeSubIFDs = true;");
} }
// -- IFormatReader API methods -- // -- IFormatReader API methods --
@Override
public void setId(String id) throws FormatException, IOException {
LOGGER.debug("setId("+id+"). before super" );
file_initialized = false;
if (Location.getIdMap().containsKey(id)) {
LOGGER.debug("id '"+id+"' is already mapped" );
content_fileName = null; // id; // maybe set to null to handle externally?
LOGGER.info("Starting initFile() method, read file directly");
super.setId(id);
} else {
// If URL, then read to memory, if normal file - use direct access
// String cameraURL = "http://192.168.0.36:2323/img"; // for testing
// just testing - ignore file name and use camera URL
// id = cameraURL;
url = null;
// String mime = null; // use to select jp4/tiff later? Or to check it is correct
content_fileName = null;
try {
url = new URL(id);
} catch (MalformedURLException e) {
LOGGER.warn("Bad URL: " + id);
}
if (url != null) {
LOGGER.info("Starting initFile() method, read "+ id +" to memory first");
//https://www.rgagnon.com/javadetails/java-0487.html
URLConnection connection = url.openConnection();
String content_disposition = connection.getHeaderField("Content-Disposition");
// raw = "attachment; filename=abc.jpg"
if(content_disposition != null && content_disposition.indexOf("=") != -1) {
content_fileName = content_disposition.split("=")[1]; //getting value after '='
// trim quotes
content_fileName= content_fileName.substring(1, content_fileName.length()-1);
} else {
String mime = connection.getContentType();
int slash = mime.lastIndexOf("/");
String suffix = slash < 0 ? "" : mime.substring(slash+1);
content_fileName = "unknown." + suffix;
}
// currentId = fileName; //???
// LOGGER.info("Mime type = "+mime);
// https://stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests
//https://stackoverflow.com/questions/2295221/java-net-url-read-stream-to-byte
InputStream is = url.openStream (); //
byte[] inBytes = IOUtils.toByteArray(is);
if (is != null) is.close();
LOGGER.info("Bytes read: "+ inBytes.length);
Location.mapFile(content_fileName, new ByteArrayHandle(inBytes));
// HashMap<String,Object> dbg_loc = Location.getIdMap();
super.setId(content_fileName);
} else { // read file normally
content_fileName = id;
LOGGER.info("read file directly");
super.setId(id);
}
}
//getReader
// super.setId(id);
LOGGER.debug("setId("+id+"). after super" );
file_initialized = true;
}
@Override @Override
protected void initFile(java.lang.String id) protected void initFile(java.lang.String id)
...@@ -117,6 +195,8 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -117,6 +195,8 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
LOGGER.info("Starting initFile() method"); LOGGER.info("Starting initFile() method");
super.initFile(id); super.initFile(id);
LOGGER.info("Ending initFile() method"); LOGGER.info("Ending initFile() method");
} }
/* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */ /* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */
...@@ -134,8 +214,14 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -134,8 +214,14 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
@Override @Override
public void close(boolean fileOnly) throws IOException { public void close(boolean fileOnly) throws IOException {
LOGGER.info("close("+fileOnly+") before super"); LOGGER.info("close("+fileOnly+") before super");
super.close(fileOnly); super.close(fileOnly); // curerent_id == null only during actual close?
LOGGER.info("close("+fileOnly+") after super"); LOGGER.info("close("+fileOnly+") after super");
if ((content_fileName != null) && file_initialized){
Location.mapFile(content_fileName, null);
file_initialized = false;
}
// HashMap<String,Object> dbg_loc = Location.getIdMap();
if (!fileOnly) { if (!fileOnly) {
// companionFile = null; // companionFile = null;
// description = null; // description = null;
...@@ -156,8 +242,35 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -156,8 +242,35 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
super.initStandardMetadata(); super.initStandardMetadata();
String comment = ifds.get(0).getComment(); // IMAGE_DESCRIPTION String comment = ifds.get(0).getComment(); // IMAGE_DESCRIPTION
LOGGER.info("initStandardMetadata() - after super()"); LOGGER.info("initStandardMetadata() - after super()");
ElphelMeta elphelMeta = new ElphelMeta(tiffParser, true); long[] maker_note = null;
Hashtable<String, String> property_table = elphelMeta.getPropertyTable(); double exposure = Double.NaN;
String date_time = null;
IFDList exifIFDs = tiffParser.getExifIFDs();
if (exifIFDs.size() > 0) {
IFD exifIFD = exifIFDs.get(0);
tiffParser.fillInIFD(exifIFD);
if (exifIFD.containsKey(IFD.MAKER_NOTE)) {
maker_note = (long[]) exifIFD.get(IFD.MAKER_NOTE);
}
if (exifIFD.containsKey(IFD.EXPOSURE_TIME)) {
Object exp = exifIFD.get(IFD.EXPOSURE_TIME);
if (exp instanceof TiffRational) {
TiffRational texp = (TiffRational) exp;
exposure = 1.0*texp.getNumerator()/texp.getDenominator();
}
}
if (exifIFD.containsKey(IFD.DATE_TIME_ORIGINAL)) {
date_time = exifIFD.get(IFD.DATE_TIME_ORIGINAL).toString();
if (exifIFD.containsKey(IFD.SUB_SEC_TIME_ORIGINAL)) {
date_time += "."+exifIFD.get(IFD.SUB_SEC_TIME_ORIGINAL).toString();
}
}
}
Hashtable<String, String> property_table = ElphelMeta.getMeta(
null, maker_note, exposure, date_time, true );
LOGGER.info("Created elphelMeta table, size="+property_table.size()); LOGGER.info("Created elphelMeta table, size="+property_table.size());
for (String key:property_table.keySet()) { for (String key:property_table.keySet()) {
addGlobalMeta(ELPHEL_PROPERTY_PREFIX+key,property_table.get(key)); addGlobalMeta(ELPHEL_PROPERTY_PREFIX+key,property_table.get(key));
...@@ -167,6 +280,7 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -167,6 +280,7 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
Integer[] tags = ifds.get(0).keySet().toArray(new Integer[0]); Integer[] tags = ifds.get(0).keySet().toArray(new Integer[0]);
LOGGER.info("initStandardMetadata() - got "+tags.length+" tags"); LOGGER.info("initStandardMetadata() - got "+tags.length+" tags");
} }
addGlobalMeta(ELPHEL_PROPERTY_PREFIX+CONTENT_FILENAME,content_fileName);
// check for ImageJ-style TIFF comment // check for ImageJ-style TIFF comment
boolean ij = checkCommentImageJ(comment); boolean ij = checkCommentImageJ(comment);
// if (ij) parseCommentImageJ(comment); // if (ij) parseCommentImageJ(comment);
...@@ -220,6 +334,22 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -220,6 +334,22 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
populateMetadataStoreImageJ(store); populateMetadataStoreImageJ(store);
} }
/**
* @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int)
*/
@Override
public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
throws FormatException, IOException
{
LOGGER.info("openBytes() - before super()");
super.openBytes(no, buf, x, y, w, h);
LOGGER.info("openBytes() - after super()");
return buf;
}
// -- Helper methods -- // -- Helper methods --
// Convert to Elphel-specific parameters // Convert to Elphel-specific parameters
......
/**
** -----------------------------------------------------------------------------**
** ImagejJp4Tiff.java
**
** Uses loci.format compatible readers for Elphel 8/16 bpp monochrome Tiff and
** JP4 files to read/parse camera files in a single url read operation by
** buffering camera data with Location.mapFile()
**
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** ImagejJp4Tiff.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/>.
** -----------------------------------------------------------------------------**
**
*/
package com.elphel.imagej.readers;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.compress.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ij.ImagePlus;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import loci.common.ByteArrayHandle;
import loci.common.Location;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory;
import loci.formats.ClassList;
import loci.formats.FormatException;
import loci.formats.IFormatReader;
import loci.formats.ImageReader;
import loci.formats.meta.IMetadata;
import loci.formats.services.OMEXMLService;
public class ImagejJp4Tiff {
// -- Constants --
private static final Logger LOGGER = LoggerFactory.getLogger(ClassList.class);
private static final boolean BYPASS_SERVICES = true;
// -- Fields --
private ImageReader reader = null;
private String content_fileName = "undefined"; // from Content-disposition
private URL url = null; // save here actual URL when reading file to memory
IMetadata omeMeta = null;
// -- Constructor --
public ImagejJp4Tiff() {
// Bypass readers.txt
ClassList<IFormatReader> classList = new ClassList<IFormatReader>(IFormatReader.class);
// classList.addClass(com.elphel.imagej.readers.ElphelTiffJp4Reader.class);
classList.addClass(com.elphel.imagej.readers.ElphelJp4Reader.class);
classList.addClass(com.elphel.imagej.readers.ElphelTiffReader.class);
if (!BYPASS_SERVICES) {
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();
}
try {
omeMeta = service.createOMEXMLMetadata();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
reader = new ImageReader(classList);
if (!BYPASS_SERVICES) {
reader.setMetadataStore(omeMeta);
}
}
// -- API methods --
public ImagePlus readTiffJp4(String path) throws IOException, FormatException {
return readTiffJp4(path, "STD_"); // null);
}
public ImagePlus readTiffJp4(String path_url, String std ) throws IOException, FormatException { // std - include non-elphel properties with prefix std
// determine if it is a file or URL and read url to memory
// If URL, then read to memory, if normal file - use direct access
url = null;
// String mime = null; // use to select jp4/tiff later? Or to check it is correct
content_fileName = null;
try {
url = new URL(path_url);
} catch (MalformedURLException e) {
LOGGER.warn("Bad URL: " + path_url);
}
if (url != null) {
LOGGER.info("Read "+ path_url +" to memory first");
URLConnection connection = url.openConnection();
String content_disposition = connection.getHeaderField("Content-Disposition");
// raw = "attachment; filename=abc.jpg"
if(content_disposition != null && content_disposition.indexOf("=") != -1) {
content_fileName = content_disposition.split("=")[1]; //getting value after '='
// trim quotes
content_fileName= content_fileName.substring(1, content_fileName.length()-1);
} else {
String mime = connection.getContentType();
int slash = mime.lastIndexOf("/");
String suffix = slash < 0 ? "" : mime.substring(slash+1);
content_fileName = "unknown." + suffix;
}
InputStream is = url.openStream (); //
byte[] inBytes = IOUtils.toByteArray(is);
if (is != null) is.close();
LOGGER.info("Bytes read: "+ inBytes.length);
Location.mapFile(content_fileName, new ByteArrayHandle(inBytes));
// HashMap<String,Object> dbg_loc = Location.getIdMap();
// super.setId(content_fileName);
} else { // read file normally
content_fileName = path_url;
LOGGER.info("read '"+path_url+"' file directly");
}
reader.setId(content_fileName);
byte [] bytes = null;
ImagePlus imp= null;
bytes = reader.openBytes(0);
int bpp = reader.getBitsPerPixel();
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();
Hashtable<String, Object> meta_hash = reader.getGlobalMetadata();
String prefix = ElphelTiffReader.ELPHEL_PROPERTY_PREFIX;
String imageName = content_fileName; // path;
String imageNameKey = prefix+ElphelTiffReader.CONTENT_FILENAME;
if (meta_hash.containsKey(imageNameKey)) {
imageName = meta_hash.get(imageNameKey).toString();
}
imp = new ImagePlus(imageName, ip); // original jp46 reader had full path as title
// first - save all as properties, later - only ELPHEL_*
for (String key:meta_hash.keySet()) {
if (key.startsWith(prefix)) {
imp.setProperty(key.substring(prefix.length()), meta_hash.get(key).toString());
} else if (std != null) {
imp.setProperty(std+(key.replace(" ","_").replace("/","_")), meta_hash.get(key).toString());
}
}
encodeProperiesToInfo(imp);
Location.mapFile(content_fileName, null);
return imp;
}
// -- Helper methods --
public static ImagePlus encodeProperiesToInfo(ImagePlus imp){
String info="<?xml version=\"1.0\" encoding=\"UTF-8\"?><properties>";
Set<Object> jp4_set;
Properties jp4_prop;
Iterator<Object> itr;
String str;
jp4_prop=imp.getProperties();
if (jp4_prop!=null) {
jp4_set=jp4_prop.keySet();
itr=jp4_set.iterator();
while(itr.hasNext()) {
str = (String) itr.next();
// if (!str.equals("Info")) info+="<"+str+">\""+jp4_prop.getProperty(str)+"\"</"+str+">";
if (!str.equals("Info")) info+="<"+str+">"+jp4_prop.getProperty(str)+"</"+str+">";
}
}
info+="</properties>\n";
imp.setProperty("Info", info);
return imp;
}
}
# This document is a configuration file identifying all file format readers
# available to Bio-Formats, and the order in which they should be used.
# Please do not edit unless you know what you are doing, see
# https://docs.openmicroscopy.org/latest/bio-formats/developers/reader-guide.html
#Elphel readers
com.elphel.imagej.readers.ElphelTiffJp4Reader # tiff,jp4
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment