//
// FlexReader.java
//
/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan,
Eric Kjellman and Brian Loranger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.formats.in;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Vector;
import javax.xml.parsers.*;
import loci.formats.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* FlexReader is a file format reader for Evotec Flex files.
* To use it, the LuraWave decoder library, lwf_jsdk2.6.jar, must be available,
* and a LuraWave license key must be specified in the lurawave.license system
* property (e.g., <code>-Dlurawave.license=XXXX</code> on the command line).
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/in/FlexReader.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/in/FlexReader.java">SVN</a></dd></dl>
*/
public class FlexReader extends BaseTiffReader {
// -- Constants --
/** Custom IFD entry for Flex XML. */
protected static final int FLEX = 65200;
/** Factory for generating SAX parsers. */
public static final SAXParserFactory SAX_FACTORY =
SAXParserFactory.newInstance();
// -- Fields --
/** Scale factor for each image. */
protected double[] factors;
// -- Constructor --
/** Constructs a new Flex reader. */
public FlexReader() { super("Evotec Flex", "flex"); }
// -- IFormatReader API methods --
/* @see loci.formats.IFormatReader#isThisType(byte[]) */
public boolean isThisType(byte[] block) { return false; }
/* @see loci.formats.FormatReader#openBytes(int, byte[]) */
public byte[] openBytes(int no, byte[] buf)
throws FormatException, IOException
{
FormatTools.assertId(currentId, true, 1);
// expand pixel values with multiplication by factor[no]
byte[] bytes = super.openBytes(no, buf);
if (core.pixelType[0] == FormatTools.UINT8) {
int num = bytes.length;
for (int i=num-1; i>=0; i--) {
int q = (int) ((bytes[i] & 0xff) * factors[no]);
bytes[i] = (byte) (q & 0xff);
}
}
if (core.pixelType[0] == FormatTools.UINT16) {
int num = bytes.length / 2;
for (int i=num-1; i>=0; i--) {
int q = (int) ((bytes[i] & 0xff) * factors[no]);
byte b0 = (byte) (q & 0xff);
byte b1 = (byte) ((q >> 8) & 0xff);
int ndx = 2 * i;
if (core.littleEndian[0]) {
bytes[ndx] = b0;
bytes[ndx + 1] = b1;
}
else {
bytes[ndx] = b1;
bytes[ndx + 1] = b0;
}
}
}
else if (core.pixelType[0] == FormatTools.UINT32) {
int num = bytes.length / 4;
for (int i=num-1; i>=0; i--) {
int q = (int) ((bytes[i] & 0xff) * factors[no]);
byte b0 = (byte) (q & 0xff);
byte b1 = (byte) ((q >> 8) & 0xff);
byte b2 = (byte) ((q >> 16) & 0xff);
byte b3 = (byte) ((q >> 24) & 0xff);
int ndx = 4 * i;
if (core.littleEndian[0]) {
bytes[ndx] = b0;
bytes[ndx + 1] = b1;
bytes[ndx + 2] = b2;
bytes[ndx + 3] = b3;
}
else {
bytes[ndx] = b3;
bytes[ndx + 1] = b2;
bytes[ndx + 2] = b1;
bytes[ndx + 3] = b0;
}
}
}
return bytes;
}
// -- Internal BaseTiffReader API methods --
/* @see loci.formats.BaseTiffReader#initStandardMetadata() */
protected void initStandardMetadata() throws FormatException, IOException {
super.initStandardMetadata();
core.orderCertain[0] = false;
// parse factors from XML
String xml = (String) TiffTools.getIFDValue(ifds[0],
FLEX, true, String.class);
Vector n = new Vector();
Vector f = new Vector();
FlexHandler handler = new FlexHandler(n, f);
try {
SAXParser saxParser = SAX_FACTORY.newSAXParser();
saxParser.parse(new ByteArrayInputStream(xml.getBytes()), handler);
}
catch (ParserConfigurationException exc) {
throw new FormatException(exc);
}
catch (SAXException exc) {
throw new FormatException(exc);
}
// verify factor count
int nsize = n.size();
int fsize = f.size();
if (debug && (nsize != fsize || nsize != core.imageCount[0])) {
LogTools.println("Warning: mismatch between image count, " +
"names and factors (count=" + core.imageCount[0] +
", names=" + nsize + ", factors=" + fsize + ")");
}
for (int i=0; i<nsize; i++) addMeta("Name " + i, n.get(i));
for (int i=0; i<fsize; i++) addMeta("Factor " + i, f.get(i));
// parse factor values
factors = new double[core.imageCount[0]];
int max = 0;
for (int i=0; i<fsize; i++) {
String factor = (String) f.get(i);
double q = 1;
try {
q = Double.parseDouble(factor);
}
catch (NumberFormatException exc) {
if (debug) {
LogTools.println("Warning: invalid factor #" + i + ": " + factor);
}
}
factors[i] = q;
if (q > factors[max]) max = i;
}
Arrays.fill(factors, fsize, factors.length, 1);
// determine pixel type
if (factors[max] > 256) core.pixelType[0] = FormatTools.UINT32;
else if (factors[max] > 1) core.pixelType[0] = FormatTools.UINT16;
else core.pixelType[0] = FormatTools.UINT8;
}
// -- Helper classes --
/** SAX handler for parsing XML. */
public class FlexHandler extends DefaultHandler {
private Vector names, factors;
public FlexHandler(Vector names, Vector factors) {
this.names = names;
this.factors = factors;
}
public void startElement(String uri,
String localName, String qName, Attributes attributes)
{
if (!qName.equals("Array")) return;
int len = attributes.getLength();
for (int i=0; i<len; i++) {
String name = attributes.getQName(i);
if (name.equals("Name")) names.add(attributes.getValue(i));
else if (name.equals("Factor")) factors.add(attributes.getValue(i));
}
}
}
}