/*
* ImageI/O-Ext - OpenSource Java Image translation Library
* http://www.geo-solutions.it/
* http://java.net/projects/imageio-ext/
* (C) 2007 - 2009, GeoSolutions
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
package it.geosolutions.imageio.matfile5.sas;
import it.geosolutions.imageio.matfile5.MatFileImageReader;
import it.geosolutions.imageio.matfile5.Utils;
import it.geosolutions.imageio.utilities.Utilities;
import java.util.HashSet;
import java.util.Set;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import org.w3c.dom.Node;
import com.jmatio.io.MatFileReader;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLDouble;
import com.jmatio.types.MLInt32;
/**
*
* @author Daniele Romagnoli, GeoSolutions SAS
*
*/
public class SASTileMetadata extends IIOMetadata {
private static Set<String> filterElements;
static {
// //
// GeoReferencing Metadata
// //
filterElements = new HashSet<String>();
filterElements.add(SASTileMetadata.SAS_TILE_RAW);
filterElements.add(SASTileMetadata.SAS_TILE_LOG);
filterElements.add(SASTileMetadata.SAS_PIXELS);
filterElements.add(SASTileMetadata.SAS_LATITUDE);
filterElements.add(SASTileMetadata.SAS_LONGITUDE);
filterElements.add(SASTileMetadata.SAS_PIXEL_DIMS);
filterElements.add(SASTileMetadata.SAS_ORIENTATION);
filterElements.add(SASTileMetadata.SAS_CHANNEL);
filterElements.add(SASTileMetadata.SAS_MU);
filterElements.add(SASTileMetadata.SAS_X);
filterElements.add(SASTileMetadata.SAS_Y);
filterElements.add(SASTileMetadata.SAS_THETA);
// Additional Metadata
filterElements.add(SASTileMetadata.SAS_PINGS);
filterElements.add(SASTileMetadata.SAS_TILE_RANGES);
// filterElements.add(SASTileMetadata.SAS_AV_VELOCITY);
// filterElements.add(SASTileMetadata.SAS_AV_ALTITUDE);
}
public static Set<String> getFilterElements() {
return new HashSet<String>(filterElements);
}
/**
* This method tries to guess if this matfile contains sas specific metadata or not.
*
* @param matReader the {@link MatFileReader} that we need to use for guessing
* @return <code>true</code> if this is a SAS matfile or <code>false</code> otherwise.
*/
public static boolean isSASFile(final MatFileReader matReader) {
MLArray sasTileData = matReader.getMLArray(SAS_TILE_RAW);
if (sasTileData != null) {
return true;
} else {
sasTileData = matReader.getMLArray(SAS_TILE_LOG);
}
if (sasTileData == null)
return false;
return true;
}
public static final String SAS_PIXELS = "pixels";
public static final String SAS_LATITUDE = "latitude";
public static final String SAS_LONGITUDE = "longitude";
public static final String SAS_ORIENTATION = "orientation";
public static final String SAS_PIXEL_DIMS = "pixel_dims";
public static final String SAS_CHANNEL = "channel";
public static final String SAS_TILE_RAW = "sas_tile_raw";
public static final String SAS_TILE_LOG = "sas_tile_log";
public static final String SAS_MU = "mu";
public static final String SAS_PINGS = "pings";
public static final String SAS_TILE_RANGES = "tile_ranges";
public static final String SAS_AV_VELOCITY = "av_velocity";
public static final String SAS_AV_ALTITUDE = "av_altitude";
public static final String SAS_X = "x";
public static final String SAS_Y = "y";
public static final String SAS_THETA = "theta";
public enum Channel {
PORT, STARBOARD, UNKNOWN;
public static Channel getChannel(String channel) {
if (channel != null && channel.trim().length() > 0) {
if (channel.equalsIgnoreCase("port"))
return PORT;
else if (channel.equalsIgnoreCase("starboard"))
return STARBOARD;
}
return UNKNOWN;
}
};
private int xPixels;
private int yPixels;
private double latitude;
private double longitude;
private double orientation;
private double xPixelDim;
private double yPixelDim;
private boolean logScale;
private int dataType;
private Channel channel;
// private MLDouble pings;
//
// private MLDouble tileRanges;
//
// private MLDouble x;
//
// private MLDouble y;
//
// private MLDouble theta;
//
// private MLDouble mu;
public SASTileMetadata(final MatFileReader matReader) {
Utilities.checkNotNull(matReader, "The provided MatFileReader was null");
MLArray sasTileData = matReader.getMLArray(SAS_TILE_RAW);
if (sasTileData != null) {
logScale = false;
} else {
logScale = true;
sasTileData = matReader.getMLArray(SAS_TILE_LOG);
}
Utilities.checkNotNull(sasTileData, "The provided input doesn't contain any valid SAS tile data");
dataType = Utils.getDatatype(sasTileData);
latitude = getDouble(matReader, SAS_LATITUDE);
longitude = getDouble(matReader, SAS_LONGITUDE);
orientation = getDouble(matReader, SAS_ORIENTATION);
final double pixelDims[] = new double[2];
// final int pixelsD[] = new int[2];
int pixels[] = null;
final int pixelType = getElementType(matReader, SAS_PIXELS);
if (pixelType == MLArray.mxDOUBLE_CLASS){
final double pixelsD[] = new double[2];
getDoubles(matReader, SAS_PIXELS, pixelsD);
pixels = new int[] {
Double.isNaN(pixelsD[0]) ? Integer.MIN_VALUE : (int) pixelsD[0],
Double.isNaN(pixelsD[1]) ? Integer.MIN_VALUE : (int) pixelsD[1] };
} else if (pixelType == MLArray.mxINT32_CLASS){
final int pixelsI[] = new int[2];
getIntegers(matReader, SAS_PIXELS, pixelsI);
pixels = pixelsI;
}
getDoubles(matReader, SAS_PIXEL_DIMS, pixelDims);
String channel = Utils.getString(matReader, SAS_CHANNEL);
// mu = (MLDouble) matReader.getMLArray(SAS_MU);
// x = (MLDouble) matReader.getMLArray(SAS_X);
// y = (MLDouble) matReader.getMLArray(SAS_Y);
// pings = (MLDouble) matReader.getMLArray(SAS_PINGS);
// theta = (MLDouble) matReader.getMLArray(SAS_THETA);
// tileRanges = (MLDouble) matReader.getMLArray(SAS_TILE_RANGES);
// Setting values
this.xPixels = pixels[0];
this.yPixels = pixels[1];
this.channel = Channel.getChannel(channel);
this.xPixelDim = pixelDims[0];
this.yPixelDim = pixelDims[1];
}
public int getDataType() {
return dataType;
}
public void setDataType(int dataType) {
this.dataType = dataType;
}
public int getXPixels() {
return xPixels;
}
public void setXPixels(int pixels) {
xPixels = pixels;
}
public int getYPixels() {
return yPixels;
}
public void setYPixels(int pixels) {
yPixels = pixels;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getOrientation() {
return orientation;
}
public void setOrientation(double orientation) {
this.orientation = orientation;
}
public boolean isLogScale() {
return logScale;
}
public void setLogScale(boolean logScale) {
this.logScale = logScale;
}
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
public double getXPixelDim() {
return xPixelDim;
}
public void setXPixelDim(double pixelDim) {
xPixelDim = pixelDim;
}
public double getYPixelDim() {
return yPixelDim;
}
public void setYPixelDim(double pixelDim) {
yPixelDim = pixelDim;
}
@Override
public Node getAsTree(String formatName) {
return null;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public void mergeTree(String formatName, Node root)
throws IIOInvalidTreeException {
}
@Override
public void reset() {
}
//TODO: Refactor and implement this.
public String getMetadataAsXML(){
return null;
}
static double[] getDoubles(final MatFileReader reader, final String element, double[] values) {
MLArray array = reader.getMLArray(element);
final MLDouble dArray = array != null ? (MLDouble) array : null;
if (dArray != null) {
final int nDims;
if (values == null) {
nDims = dArray.getM();
values = new double[nDims];
} else
nDims = values.length;
for (int i = 0; i < nDims; i++) {
values[i] = dArray.get(i).doubleValue();
}
} else {
if (values == null) {
values = new double[] { Double.NaN, Double.NaN };
} else {
for (int i = 0; i < values.length; i++) {
values[i] = Double.NaN;
}
}
}
return values;
}
static int[] getIntegers(final MatFileReader reader, final String element, int[] values) {
MLArray array = reader.getMLArray(element);
final MLInt32 iArray = array != null ? (MLInt32) array : null;
if (iArray != null) {
final int nDims;
if (values == null) {
nDims = iArray.getM();
values = new int[nDims];
} else
nDims = values.length;
for (int i = 0; i < nDims; i++) {
values[i] = iArray.get(i).intValue();
}
} else {
if (values == null) {
values = new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE};
} else {
for (int i = 0; i < values.length; i++) {
values[i] = Integer.MAX_VALUE;
}
}
}
return values;
}
static double getDouble(final MatFileReader reader, final String element){
return getDouble(reader, element,0);
}
static double getDouble(final MatFileReader reader, final String element, final int index) {
double value = Double.NaN;
if (element != null && reader!=null) {
MLArray array = reader.getMLArray(element);
final MLDouble arrayD = array != null ? (MLDouble) array : null;
if (arrayD != null)
value = arrayD.get(index).doubleValue();
}
return value;
}
static int getElementType (final MatFileReader reader, final String element){
Utilities.checkNotNull(reader, "The provided MatFileReader is null");
if (reader != null){
final MLArray array = reader.getMLArray(element);
return Utils.getMatDatatype(array);
}
return MLArray.mxUNKNOWN_CLASS;
}
}