Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
imagej-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
imagej-elphel
Commits
2397e946
Commit
2397e946
authored
May 13, 2019
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More on JP4+Tiff reading with bioformatrs.
parent
fb75351e
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
945 additions
and
187 deletions
+945
-187
.gitignore
.gitignore
+2
-1
pom.xml
pom.xml
+2
-1
EyesisTiff.java
src/main/java/EyesisTiff.java
+104
-72
JP46_Reader_camera.java
src/main/java/JP46_Reader_camera.java
+72
-7
ElphelJp4Reader.java
src/main/java/com/elphel/imagej/readers/ElphelJp4Reader.java
+299
-0
ElphelMeta.java
src/main/java/com/elphel/imagej/readers/ElphelMeta.java
+89
-101
ElphelTiffReader.java
...main/java/com/elphel/imagej/readers/ElphelTiffReader.java
+135
-5
ImagejJp4Tiff.java
src/main/java/com/elphel/imagej/readers/ImagejJp4Tiff.java
+235
-0
readers1.txt
src/main/resources/readers1.txt
+7
-0
No files found.
.gitignore
View file @
2397e946
...
...
@@ -8,4 +8,5 @@ attic
*.log
FOCUS-PSF*
src/main/resources/trained_model
bioformats
\ No newline at end of file
bioformats*.*
metadata*.*
pom.xml
View file @
2397e946
...
...
@@ -88,7 +88,8 @@
<dependency>
<groupId>
ome
</groupId>
<artifactId>
loci_tools
</artifactId>
<version>
5.9.0
</version>
<version>
6.1.0-SNAPSHOT
</version>
<type>
java-source
</type>
</dependency>
</dependencies>
...
...
src/main/java/EyesisTiff.java
View file @
2397e946
...
...
@@ -31,21 +31,32 @@ 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.StringReader
;
import
java.io.UnsupportedEncodingException
;
import
java.lang.reflect.Array
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
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.xml.parsers.DocumentBuilder
;
import
javax.xml.parsers.DocumentBuilderFactory
;
import
javax.xml.parsers.ParserConfigurationException
;
import
org.slf4j.Logger
;
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;
...
...
@@ -55,20 +66,15 @@ 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
;
...
...
@@ -86,6 +92,7 @@ public class EyesisTiff {
defaultClasses
=
new
ClassList
<
IFormatReader
>(
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.
null
);
// @param location Class indicating which package to search for the file.
}
...
...
@@ -109,43 +116,14 @@ 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
);
return
readTiff
(
path
,
"STD_"
);
// null);
}
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
);
public
ImagePlus
readTiff
(
String
path
,
String
std
)
{
// std - include non-elphel properties with prefix std
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
;
try
{
factory
=
new
ServiceFactory
();
...
...
@@ -153,6 +131,7 @@ public class EyesisTiff {
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
OMEXMLService
service
=
null
;
try
{
service
=
factory
.
getInstance
(
OMEXMLService
.
class
);
...
...
@@ -160,6 +139,7 @@ public class EyesisTiff {
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
IMetadata
omeMeta
=
null
;
try
{
omeMeta
=
service
.
createOMEXMLMetadata
();
...
...
@@ -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://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
//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
());
//
BaseTiffReader reader = new BaseTiffReader("Base_tiff_reader","tiff"
);
//
ImageReader reader = new ImageReader(classList
);
reader
.
setMetadataStore
(
omeMeta
);
try
{
reader
.
setId
(
inId
);
...
...
@@ -187,32 +172,10 @@ public class EyesisTiff {
//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
{
...
...
@@ -245,11 +208,26 @@ public class EyesisTiff {
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
Hashtable
<
String
,
Object
>
meta_hash
=
reader
.
getGlobalMetadata
();
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
{
reader
.
close
();
}
catch
(
IOException
e
)
{
...
...
@@ -662,4 +640,58 @@ the type of pixel data in this file getPixelType()
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
;
}
}
src/main/java/JP46_Reader_camera.java
View file @
2397e946
...
...
@@ -59,6 +59,8 @@ import org.w3c.dom.NodeList;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
com.elphel.imagej.readers.ImagejJp4Tiff
;
import
ij.IJ
;
import
ij.ImageJ
;
import
ij.ImagePlus
;
...
...
@@ -75,6 +77,7 @@ import ij.process.ImageConverter;
import
ij.process.ImageProcessor
;
import
ij.text.TextWindow
;
import
loci.common.RandomAccessInputStream
;
import
loci.formats.FormatException
;
import
loci.formats.tiff.IFD
;
import
loci.formats.tiff.IFDList
;
import
loci.formats.tiff.TiffParser
;
...
...
@@ -96,7 +99,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
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_new
=
"towp/wait/bimg"
;
// will always wait for the next image (repetitive acquisitions get new images)
public
String
camera_jp46settings
=
""
;
...
...
@@ -322,6 +325,10 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
if
(
demux
)
showImage
=
false
;
double
[]
xtraExif
=
new
double
[
1
];
// ExposureTime
double
[]
lla
=
null
;
imp
=
openJpegOrGif
(
directory
,
fileName
);
imp
.
show
();
if
(
imp
!=
null
)
return
imp
;
try
{
imp
=
openJpegOrGif
(
directory
,
fileName
);
if
(
imp
==
null
)
{
...
...
@@ -390,7 +397,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
String
arg
,
boolean
scale
,
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
;
ImagePlus
imp
=
null
;
boolean
reuse_imp
=
false
;
...
...
@@ -399,14 +434,14 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
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
{
imp
=
openJpegOrGifUsingURL
(
url
);
if
(
imp
==
null
)
{
IJ
.
showMessage
(
"JP46 Reader Error"
,
"Could not open the URL: "
+
url
+
" as JPEG/JP46"
);
}
else
{
if
((
imp_src
==
null
)
&&
showImage
)
{
// System.out.println("show() 1");
// System.out.println("show() 1");
imp
.
show
();
/* Shows before re-ordering*/
}
/// 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 {
if
(
reuse_imp
)
{
imp
=
imp_src
;
}
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 */
}
if
((
xtraExif
!=
null
)
&&
!
Double
.
isNaN
(
xtraExif
[
0
])){
...
...
@@ -1042,6 +1077,35 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
/* Modified from Opener.java */
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
;
boolean
isTiff
=
false
;
Image
img
=
Toolkit
.
getDefaultToolkit
().
createImage
(
dir
+
name
);
...
...
@@ -1073,8 +1137,8 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
fi
=
imp
.
getFileInfo
();
// 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;
EyesisTiff ET = new EyesisTiff();
ImagePlus imptiff = ET.readTiff(path);
...
...
@@ -1093,6 +1157,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
Frame log = WindowManager.getFrame("Log");
if (log!=null) log.toFront();
}
*/
}
...
...
src/main/java/com/elphel/imagej/readers/ElphelJp4Reader.java
0 → 100644
View file @
2397e946
/**
** -----------------------------------------------------------------------------**
** ElphelJp4Reader.java
**
** loci.format compatible reader for Elphel JP4 files
**
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** ElphelTiffReader.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.util.Date
;
import
java.util.HashMap
;
import
java.util.Hashtable
;
import
org.apache.commons.compress.utils.IOUtils
;
import
org.joda.time.DateTime
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
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.FormatException
;
import
loci.formats.FormatTools
;
import
loci.formats.in.ImageIOReader
;
import
loci.formats.in.MetadataLevel
;
import
loci.formats.services.EXIFService
;
//import loci.formats.services.EXIFService;
import
ome.xml.meta.MetadataStore
;
import
ome.xml.model.primitives.Timestamp
;
//ElphelTiffReader
public
class
ElphelJp4Reader
extends
ImageIOReader
{
// -- Constants --
public
static
final
String
MAKER_NOTE
=
"Makernote"
;
public
static
final
String
SUB_SEC_TIME_ORIGINAL
=
"Sub-Sec Time Original"
;
public
static
final
String
EXPOSURE_TIME
=
"Exposure Time"
;
public
static
final
String
DATE_TIME_ORIGINAL
=
"Date/Time Original"
;
public
static
final
String
ELPHEL_PROPERTY_PREFIX
=
"ELPHEL_"
;
public
static
final
String
CONTENT_FILENAME
=
"CONTENT_FILENAME"
;
/** Logger for this class. */
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
ElphelTiffReader
.
class
);
// -- Fields --
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
ElphelTiffReader
elphelTiffReader
=
null
;
// private ImageReader helperReader;
// -- Constructor --
/** Constructs a new Tiff reader. */
public
ElphelJp4Reader
()
{
super
(
"JP4"
,
new
String
[]
{
"jp4"
});
// mergeSubIFDs = true; // false;
suffixNecessary
=
true
;
// false
suffixSufficient
=
true
;
// false;
LOGGER
.
info
(
"ElphelTiffReader(), after super()"
);
elphelTiffReader
=
new
ElphelTiffReader
();
}
// -- IFormatReader API methods --
/* @see loci.formats.IFormatReader#isThisType(String, boolean) */
@Override
public
boolean
isThisType
(
String
name
,
boolean
open
)
{
if
(
open
)
{
return
super
.
isThisType
(
name
,
open
);
}
return
checkSuffix
(
name
,
getSuffixes
());
}
/* @see loci.formats.IFormatReader#isThisType(RandomAccessInputStream) */
@Override
public
boolean
isThisType
(
RandomAccessInputStream
stream
)
throws
IOException
{
final
int
blockLen
=
4
;
if
(!
FormatTools
.
validStream
(
stream
,
blockLen
,
false
))
return
false
;
byte
[]
signature
=
new
byte
[
blockLen
];
stream
.
read
(
signature
);
if
(
signature
[
0
]
!=
(
byte
)
0xff
||
signature
[
1
]
!=
(
byte
)
0xd8
||
signature
[
2
]
!=
(
byte
)
0xff
||
(
signature
[
3
]
&
0xf0
)
==
0
)
{
return
false
;
}
return
true
;
}
@Override
public
void
setId
(
String
id
)
throws
FormatException
,
IOException
{
// same as for tiff?
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
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
;
}
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected
void
initFile
(
String
id
)
throws
FormatException
,
IOException
{
LOGGER
.
debug
(
"initFile("
+
id
+
"), currentId="
+
currentId
+
", before super"
);
try
{
super
.
initFile
(
id
);
// fails class_not_found
}
catch
(
IllegalArgumentException
e
)
{
throw
new
FormatException
(
e
);
}
LOGGER
.
debug
(
"initFile("
+
id
+
"), currentId="
+
currentId
+
", after super"
);
// elphelTiffReader.setId(id); //error here - invalid tiff file
// Below needs to be modified - EXIFService does not work with mapFile
MetadataStore
store
=
makeFilterMetadata
();
LOGGER
.
info
(
"Parsing JPEG EXIF data"
);
HashMap
<
String
,
String
>
tags
=
null
;
try
{
EXIFService
exif
=
new
ServiceFactory
().
getInstance
(
EXIFService
.
class
);
if
(
exif
==
null
)
{
return
;
}
exif
.
initialize
(
id
);
// Set the acquisition date
Date
date
=
exif
.
getCreationDate
();
if
(
date
!=
null
)
{
Timestamp
timestamp
=
new
Timestamp
(
new
DateTime
(
date
));
store
.
setImageAcquisitionDate
(
timestamp
,
0
);
}
tags
=
exif
.
getTags
();
for
(
String
tagName
:
tags
.
keySet
())
{
addGlobalMeta
(
tagName
,
tags
.
get
(
tagName
));
}
//{Makernote=105455 131072 127570 300581 171508736 171508736 171508736 171508736 169869312 124780556 1118544 0 0 327779 648 1296, Sub-Sec Time Original=560439, Exposure Time=11167/500000 sec, Date/Time Original=2019:05:13 04:30:26}
}
catch
(
ServiceException
e
)
{
LOGGER
.
debug
(
"Could not parse EXIF data"
,
e
);
}
catch
(
DependencyException
e
)
{
LOGGER
.
debug
(
"Could not parse EXIF data"
,
e
);
}
long
[]
maker_note
=
null
;
double
exposure
=
Double
.
NaN
;
String
date_time
=
null
;
if
(
tags
.
containsKey
(
MAKER_NOTE
)){
String
[]
smn
=
tags
.
get
(
MAKER_NOTE
).
split
(
" "
);
maker_note
=
new
long
[
smn
.
length
];
for
(
int
i
=
0
;
i
<
maker_note
.
length
;
i
++)
{
maker_note
[
i
]
=
Integer
.
parseInt
(
smn
[
i
]);
}
}
if
(
tags
.
containsKey
(
EXPOSURE_TIME
)){
String
[]
s
=
tags
.
get
(
EXPOSURE_TIME
).
split
(
"/"
);
exposure
=
1.0
*
Integer
.
parseInt
(
s
[
0
])
/
Integer
.
parseInt
(
s
[
1
].
split
(
" "
)[
0
]);
}
if
(
tags
.
containsKey
(
DATE_TIME_ORIGINAL
)){
date_time
=
tags
.
get
(
DATE_TIME_ORIGINAL
);
if
(
tags
.
containsKey
(
SUB_SEC_TIME_ORIGINAL
)){
date_time
+=
tags
.
get
(
SUB_SEC_TIME_ORIGINAL
);
}
}
Hashtable
<
String
,
String
>
property_table
=
ElphelMeta
.
getMeta
(
null
,
maker_note
,
exposure
,
date_time
,
true
);
LOGGER
.
info
(
"Created elphelMeta table, size="
+
property_table
.
size
());
for
(
String
key:
property_table
.
keySet
())
{
addGlobalMeta
(
ELPHEL_PROPERTY_PREFIX
+
key
,
property_table
.
get
(
key
));
}
MetadataLevel
level
=
getMetadataOptions
().
getMetadataLevel
();
if
(
level
!=
MetadataLevel
.
MINIMUM
)
{
// Integer[] tags = ifds.get(0).keySet().toArray(new Integer[0]);
// LOGGER.info("initStandardMetadata() - got "+tags.length+" tags");
}
addGlobalMeta
(
ELPHEL_PROPERTY_PREFIX
+
CONTENT_FILENAME
,
content_fileName
);
}
/* @see loci.formats.IFormatReader#close(boolean) */
@Override
public
void
close
(
boolean
fileOnly
)
throws
IOException
{
HashMap
<
String
,
Object
>
dbg_loc
=
Location
.
getIdMap
();
String
saveCurrentId
=
currentId
;
currentId
=
null
;
LOGGER
.
info
(
"close("
+
fileOnly
+
") before super"
);
super
.
close
(
fileOnly
);
// curerent_id == null only during actual close?
LOGGER
.
info
(
"close("
+
fileOnly
+
") after super"
);
currentId
=
saveCurrentId
;
if
((
content_fileName
!=
null
)
&&
file_initialized
){
Location
.
mapFile
(
content_fileName
,
null
);
file_initialized
=
false
;
}
dbg_loc
=
Location
.
getIdMap
();
if
(!
fileOnly
)
{
// companionFile = null;
// description = null;
// calibrationUnit = null;
// physicalSizeZ = null;
// timeIncrement = null;
// xOrigin = null;
// yOrigin = null;
}
}
}
src/main/java/com/elphel/imagej/readers/ElphelMeta.java
View file @
2397e946
...
...
@@ -29,40 +29,26 @@ import java.util.Hashtable;
//import ij.IJ;
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
{
private
Hashtable
<
String
,
String
>
property_table
=
null
;
public
ElphelMeta
(
TiffParser
tiffParser
,
boolean
scale
)
throws
FormatException
,
IOException
{
IFDList
exifIFDs
=
tiffParser
.
getExifIFDs
();
// private Hashtable<String, String> property_table = null;
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
>
();
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
))
{
String
dt
=
exifIFD
.
get
(
IFD
.
DATE_TIME_ORIGINAL
).
toString
();
if
(
exifIFD
.
containsKey
(
IFD
.
SUB_SEC_TIME_ORIGINAL
))
{
dt
+=
"."
+
exifIFD
.
get
(
IFD
.
SUB_SEC_TIME_ORIGINAL
).
toString
();
}
property_table
.
put
(
"DATE_TIME"
,
dt
);
if
(!
Double
.
isNaN
(
exposure
))
{
property_table
.
put
(
"EXPOSURE"
,
String
.
format
(
"%f"
,
exposure
));
}
if
(
date_time
==
null
)
{
property_table
.
put
(
"DATE_TIME"
,
date_time
);
}
if
(
maker_note
!=
null
)
{
// copied from JP4_Reader_cam
// Add GPS tags when there will be images to experiment (or while reimplementing JP4 reader)
double
[]
gains
=
new
double
[
4
];
...
...
@@ -96,7 +82,6 @@ public class ElphelMeta {
long
CORING_INDEX_Y
=
0
;
long
CORING_INDEX_C
=
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 */
gains
[
i
]=
maker_note
[
i
]/
65536.0
;
blacks
[
i
]=(
maker_note
[
i
+
4
]>>
24
)/
256.0
;
...
...
@@ -193,7 +178,7 @@ public class ElphelMeta {
property_table
.
put
(
"FLIPV2"
,
FLIPV2
?
"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
)
{
swapArrayElements
(
gains
,
1
,
3
);
swapArrayElements
(
gains
,
0
,
2
);
...
...
@@ -215,9 +200,6 @@ public class ElphelMeta {
swapArrayElements
(
gamma_scales
,
3
,
2
);
}
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 */
min_gain
=
2.0
*
gains
[
0
];
for
(
i
=
0
;
i
<
4
;
i
++)
{
...
...
@@ -237,7 +219,7 @@ public class ElphelMeta {
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
)
{
swapArrayElements
(
satValue
,
1
,
3
);
swapArrayElements
(
satValue
,
0
,
2
);
...
...
@@ -250,19 +232,25 @@ public class ElphelMeta {
property_table
.
put
(
"saturation_"
+
i
,
String
.
format
(
"%f"
,
satValue
[
i
]));
}
}
public
Hashtable
<
String
,
String
>
getPropertyTable
(){
return
property_table
;
}
// public Hashtable<String, String> getPropertyTable(){
// return property_table;
// }
// -- Helper methods --
void
swapArrayElements
(
double
[]
arr
,
int
i
,
int
j
)
{
static
void
swapArrayElements
(
double
[]
arr
,
int
i
,
int
j
)
{
double
tmp
=
arr
[
i
];
arr
[
i
]=
arr
[
j
];
arr
[
j
]=
tmp
;
}
void
swapArrayElements
(
long
[]
arr
,
int
i
,
int
j
)
{
static
void
swapArrayElements
(
long
[]
arr
,
int
i
,
int
j
)
{
long
tmp
=
arr
[
i
];
arr
[
i
]=
arr
[
j
];
arr
[
j
]=
tmp
;
...
...
@@ -270,7 +258,7 @@ public class ElphelMeta {
/* reverses gamma calculations in the camera
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
;
double
x
,
black256
,
k
;
int
[]
gtable
=
new
int
[
257
];
...
...
src/main/java/com/elphel/imagej/readers/ElphelTiffReader.java
View file @
2397e946
...
...
@@ -27,15 +27,25 @@
*/
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.util.Hashtable
;
import
org.apache.commons.compress.utils.IOUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
loci.common.ByteArrayHandle
;
import
loci.common.Location
;
import
loci.formats.FormatException
;
import
loci.formats.in.MetadataLevel
;
import
loci.formats.in.TiffReader
;
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)
...
...
@@ -72,7 +82,9 @@ IFD.java public static final int MAKER_NOTE = 37500;
public
class
ElphelTiffReader
extends
TiffReader
{
// BaseTiffReader {
// -- Constants --
public
static
final
String
ELPHEL_PROPERTY_PREFIX
=
"ELPHEL_"
;
public
static
final
String
CONTENT_FILENAME
=
"CONTENT_FILENAME"
;
/** Merge SubIFDs into the main IFD list. */
// protected transient boolean mergeSubIFDs = true; // false;
...
...
@@ -89,7 +101,10 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
// public static final int IMAGEJ_TAG = 50839;
// -- 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 description;
// private String calibrationUnit;
...
...
@@ -102,12 +117,75 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
/** Constructs a new Tiff reader. */
public
ElphelTiffReader
()
{
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;"
);
}
// -- 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
protected
void
initFile
(
java
.
lang
.
String
id
)
...
...
@@ -117,6 +195,8 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
LOGGER
.
info
(
"Starting initFile() method"
);
super
.
initFile
(
id
);
LOGGER
.
info
(
"Ending initFile() method"
);
}
/* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */
...
...
@@ -134,8 +214,14 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
@Override
public
void
close
(
boolean
fileOnly
)
throws
IOException
{
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"
);
if
((
content_fileName
!=
null
)
&&
file_initialized
){
Location
.
mapFile
(
content_fileName
,
null
);
file_initialized
=
false
;
}
// HashMap<String,Object> dbg_loc = Location.getIdMap();
if
(!
fileOnly
)
{
// companionFile = null;
// description = null;
...
...
@@ -156,8 +242,35 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
super
.
initStandardMetadata
();
String
comment
=
ifds
.
get
(
0
).
getComment
();
// IMAGE_DESCRIPTION
LOGGER
.
info
(
"initStandardMetadata() - after super()"
);
ElphelMeta
elphelMeta
=
new
ElphelMeta
(
tiffParser
,
true
);
Hashtable
<
String
,
String
>
property_table
=
elphelMeta
.
getPropertyTable
();
long
[]
maker_note
=
null
;
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
());
for
(
String
key:
property_table
.
keySet
())
{
addGlobalMeta
(
ELPHEL_PROPERTY_PREFIX
+
key
,
property_table
.
get
(
key
));
...
...
@@ -167,6 +280,7 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
Integer
[]
tags
=
ifds
.
get
(
0
).
keySet
().
toArray
(
new
Integer
[
0
]);
LOGGER
.
info
(
"initStandardMetadata() - got "
+
tags
.
length
+
" tags"
);
}
addGlobalMeta
(
ELPHEL_PROPERTY_PREFIX
+
CONTENT_FILENAME
,
content_fileName
);
// check for ImageJ-style TIFF comment
boolean
ij
=
checkCommentImageJ
(
comment
);
// if (ij) parseCommentImageJ(comment);
...
...
@@ -220,6 +334,22 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
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 --
// Convert to Elphel-specific parameters
...
...
src/main/java/com/elphel/imagej/readers/ImagejJp4Tiff.java
0 → 100644
View file @
2397e946
/**
** -----------------------------------------------------------------------------**
** 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
;
}
}
src/main/resources/readers1.txt
0 → 100644
View file @
2397e946
# 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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment