package it.geosolutions.imageio.plugins.jhdf.aps;
import it.geosolutions.hdf.object.h4.H4Attribute;
import it.geosolutions.hdf.object.h4.H4SDS;
import it.geosolutions.imageio.plugins.jhdf.AbstractHDFImageReader;
import it.geosolutions.imageio.plugins.jhdf.SubDatasetInfo;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
/**
* Specific Implementation of the AbstractHDFImageReader
needed to
* work on HDF produced by the Navy's APS (Automated Processing System)
*
* @author Romagnoli Daniele
*/
public class APSImageReader extends AbstractHDFImageReader {
public APSImageReader(ImageReaderSpi originatingProvider) {
super(originatingProvider);
}
/** The Products Dataset List contained within the APS File */
private String[] productList;
private APSImageMetadata imageMetadata;
private APSStreamMetadata streamMetadata;
private void checkImageIndex(int imageIndex) {
// TODO: Implements the imageIndex coherency check
// if (imageIndex < 0
// || (!hasSubDatasets && imageIndex > 0)
// || (hasSubDatasets && ((nSubdatasets == 0 && imageIndex > 0) ||
// (nSubdatasets != 0 && (imageIndex > nSubdatasets))))) {
//
// // The specified imageIndex is not valid.
// // Retrieving the valid image index range.
// final int validImageIndex = hasSubDatasets ? nSubdatasets
// : 0;
// StringBuffer sb = new StringBuffer(
// "Illegal imageIndex specified = ").append(imageIndex)
// .append(", while the valid imageIndex");
// if (validImageIndex > 0)
// // There are N Subdatasets.
// sb.append(" range should be (0,").append(validImageIndex - 1)
// .append(")!!");
// else
// // Only the imageIndex 0 is valid.
// sb.append(" should be only 0!");
// throw new IndexOutOfBoundsException(sb.toString());
// }
}
/**
* Retrieve APS main information.
*
* @param root
*
* @throws Exception
*/
protected void initializeProfile() throws Exception {
final int nSDS = h4SDSCollection.getNumSDS();
int subdatasetsNum = 0;
final H4Attribute attrib = h4SDSCollection.getAttribute("prodList");
if (attrib!=null){
Object attribValue = attrib.getValues();
byte[] bb = (byte[]) attribValue;
final int size = bb.length;
StringBuffer sb = new StringBuffer(size);
for (int i = 0; i < size && bb[i] != 0; i++) {
sb.append(new String(bb, i, 1));
}
final String values = sb.toString();
String products[] = values.split(",");
productList = refineProductList(products);
subdatasetsNum = productList.length;
}
subDatasetsMap = new LinkedHashMap(subdatasetsNum);
sourceStructure = new SourceStructure(subdatasetsNum);
// Scanning all the datasets
for (int i = 0; i < nSDS; i++) {
final H4SDS sds = h4SDSCollection.getH4SDS(i);
final String name = sds.getName();
boolean added = false;
for (int j = 0; j < subdatasetsNum; j++) {
// Checking if the actual dataset is a product.
if (name.equals(productList[j])) {
// Updating the subDatasetsMap map
subDatasetsMap.put(name, sds);
// retrieving subDataset main properties
// (Rank, dims, chunkSize)
final int rank = sds.getRank();
final int[] dims = sds.getDimSizes();
final int[] chunkSize = sds.getChunkSizes();
final int[] subDatasetDims = new int[rank];
final int[] subDatasetChunkSize;
int datasetSize = 1;
// copying values to avoid altering dataset
// fields.
for (int k = 0; k < rank; k++) {
subDatasetDims[k] = dims[k];
// when rank > 2, X and Y are the last
// 2 coordinates. As an instance, for a
// 3D subdatasets, 3rd dimension has
// index 0.
if (k < rank - 2)
datasetSize *= dims[k];
}
if (chunkSize != null) {
subDatasetChunkSize = new int[rank];
for (int k = 0; k < rank; k++)
subDatasetChunkSize[k] = chunkSize[k];
} else
subDatasetChunkSize = null;
final int dt = sds.getDatatype();
// instantiating a SubDatasetInfo
SubDatasetInfo dsInfo = new SubDatasetInfo(name, rank,
subDatasetDims, subDatasetChunkSize, dt);
sourceStructure.setSubDatasetSize(j, datasetSize);
sourceStructure.setSubDatasetInfo(j, dsInfo);
added=true;
break;
}
}
if(!added)
sds.close();
}
}
/**
* Reduces the product's list by removing not interesting ones. As an
* instance the dataset containing l2_flags will be not presented.
*
* @param products
* The originating String
array containing the
* list of products to be checked.
* @return A String
array containing a refined list of
* products
*/
private String[] refineProductList(String[] products) {
final int inputProducts = products.length;
int j = 0;
final boolean[] accepted = new boolean[inputProducts];
for (int i = 0; i < inputProducts; i++)
if (isAcceptedItem(products[i])) {
accepted[i] = true;
j++;
} else
accepted[i] = false;
if (j == inputProducts)
return products;
final String[] returnedProductsList = new String[j];
j = 0;
for (int i = 0; i < inputProducts; i++) {
if (accepted[i])
returnedProductsList[j++] = products[i];
}
return returnedProductsList;
}
protected boolean isAcceptedItem(String productName) {
// if (attribName.endsWith("_flags"))
// return false;
if (APSProperties.apsProducts.getHDFProduct(productName) != null)
return true;
return false;
}
public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
checkImageIndex(imageIndex);
SubDatasetInfo sdInfo = sourceStructure
.getSubDatasetInfo(retrieveSubDatasetIndex(imageIndex));
if (imageMetadata == null)
imageMetadata = new APSImageMetadata(sdInfo);
return imageMetadata;
}
public int getNumImages(boolean allowSearch) throws IOException {
return sourceStructure.getNSubdatasets();
}
public IIOMetadata getStreamMetadata() throws IOException {
if (streamMetadata == null)
streamMetadata = new APSStreamMetadata(h4SDSCollection);
return streamMetadata;
}
public void dispose() {
super.dispose();
synchronized (mutex) {
final Set set = subDatasetsMap.keySet();
final Iterator setIt = set.iterator();
// Cleaning HashMap
while (setIt.hasNext()) {
// Dataset ds = (Dataset) subDatasetsMap.get(setIt.next());
// TODO:Restore original properties?
// TODO: Close datasets
}
subDatasetsMap.clear();
}
}
public void reset() {
super.reset();
streamMetadata = null;
imageMetadata = null;
productList = null;
}
protected int getBandNumberFromProduct(String productName) {
return APSProperties.apsProducts.getHDFProduct(productName).getNBands();
}
}