/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2016, Geomatys
*
* 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;
* version 2.1 of the License.
*
* 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 org.geotoolkit.metadata.geotiff;
import java.util.Collection;
import com.sun.media.imageio.plugins.tiff.GeoTIFFTagSet;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import javax.imageio.metadata.IIOMetadataNode;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import static com.sun.media.imageio.plugins.tiff.GeoTIFFTagSet.*;
import static org.geotoolkit.metadata.geotiff.GeoTiffConstants.*;
import static org.geotoolkit.util.DomUtilities.*;
/**
* Set of convenient methods to manipulate Dom nodes specific to geotiff.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public final class GeoTiffMetaDataUtils {
/**
* Return the first node in the given node children which number attribut value
* match the given number.
*/
static Node getNodeByNumber(final Node parent, final int number) {
final NodeList lst = parent.getChildNodes();
for(int i=0,n=lst.getLength();i<n;i++){
final Node child = lst.item(i);
//check it's the node we are looking for
final String attVal = getAttributeValue(child,ATT_NUMBER);
if (attVal != null && Integer.parseInt(attVal) == number) {
return child;
}
}
return null;
}
/**
* Return the first node in the given node children which name attribute
* matchs the given name.
*/
static Node getNodeByAttributeName(final Node parent, final String name) {
final NodeList lst = parent.getChildNodes();
for(int i = 0, n = lst.getLength(); i < n; i++) {
final Node child = lst.item(i);
if (name.equalsIgnoreCase(getAttributeValue(child, ATT_NAME))) {
return child;
}
}
return null;
}
/**
* Returns the attribut value or null if attribut does not exist.
*/
static String getAttributeValue(final Node candidate, final String attributName){
final NamedNodeMap attributs = candidate.getAttributes();
if(attributs != null){
final Node attribut = attributs.getNamedItem(attributName);
if(attribut != null){
return attribut.getNodeValue();
}
}
return null;
}
/**
* Read a TIFFShort node value.
*/
static int readTiffShort(final Node candidate) {
return Integer.parseInt(getAttributeValue(candidate, ATT_VALUE)) & 0xFFFF;
}
/**
* Read a TIFFShorts node values.
*/
static int[] readTiffShorts(final Node candidate) {
final NodeList lst = candidate.getChildNodes();
final int size = lst.getLength();
if(size == 0){
return null;
}
final int[] shorts = new int[size];
for(int i=0;i<shorts.length;i++){
shorts[i] = readTiffShort(lst.item(i));
}
return shorts;
}
/**
* Read a TIFFLong node value.
*/
static long readTiffLong(final Node candidate) {
return Long.parseLong(getAttributeValue(candidate, ATT_VALUE));
}
/**
* Read a TIFFLongs node values.
*/
static long[] readTiffLongs(final Node candidate) {
final NodeList lst = candidate.getChildNodes();
final int size = lst.getLength();
if(size == 0){
return null;
}
final long[] longs = new long[size];
for(int i=0;i<longs.length;i++){
longs[i] = readTiffLong(lst.item(i));
}
return longs;
}
/**
* Read a TIFFDouble node value.
*/
static double readTiffDouble(final Node candidate) {
return Double.parseDouble(getAttributeValue(candidate, ATT_VALUE));
}
/**
* Read a TIFFdoubles node values.
*/
static double[] readTiffDoubles(final Node candidate) {
final NodeList lst = candidate.getChildNodes();
final int size = lst.getLength();
if(size == 0){
return null;
}
final double[] doubles = new double[size];
for(int i=0;i<doubles.length;i++){
doubles[i] = readTiffDouble(lst.item(i));
}
return doubles;
}
/**
* Read a TIFFAscii node value.
*/
static String readTiffAscii(final Node candidate) {
final String valueAttribute = getAttributeValue(candidate, ATT_VALUE);
return valueAttribute;
}
/**
* Read a TIFFAsciis node values.
* There are not several String here, they are all concatenate in a single
* String in one ASCII sub node.
*/
static String readTiffAsciis(final Node candidate) {
final Node subNode = getNodeByLocalName(candidate, TAG_GEOTIFF_ASCII);
if(subNode != null){
return readTiffAscii(subNode);
}
return "";
}
/**
* Create a dom Node, a special IIOMetadataNode.
*/
static Element createNode(final String name){
return new IIOMetadataNode(name);
}
/**
* Create a TiffField node with id and name from the TIFFTag description.
*/
static Node createTiffField(final TIFFTag tag){
return createTiffField(tag.getNumber(),tag.getName());
}
/**
* Create a Tiffield node.
*/
static Node createTiffField(final int number, final String name){
final Element ele = createNode(TAG_GEOTIFF_FIELD);
ele.setAttribute(ATT_NUMBER, Integer.toString(number));
ele.setAttribute(ATT_NAME, name);
return ele;
}
/**
* Create a TIFFShort node.
*/
static Node createTiffShort(final int value) {
final Element ele = createNode(TAG_GEOTIFF_SHORT);
ele.setAttribute(ATT_VALUE, Long.toString(value));
return ele;
}
/**
* Create a TIFFShorts node.
*/
static Node createTiffShorts(final int ... ints) {
final Element ele = createNode(TAG_GEOTIFF_SHORTS);
for(final int i : ints){
ele.appendChild(createTiffShort(i));
}
return ele;
}
/**
* Create a TIFFLong node.
*/
static Node createTiffLong(final long value) {
final Element ele = createNode(TAG_GEOTIFF_LONG);
ele.setAttribute(ATT_VALUE, Long.toString(value));
return ele;
}
/**
* Create a TIFFLongs node.
*/
static Node createTiffLongs(final long ... longs) {
final Element ele = createNode(TAG_GEOTIFF_LONGS);
for(final long l : longs){
ele.appendChild(createTiffLong(l));
}
return ele;
}
/**
* Create a TIFFDouble node.
*/
static Node createTiffDouble(final double value) {
final Element ele = createNode(TAG_GEOTIFF_DOUBLE);
ele.setAttribute(ATT_VALUE, Double.toString(value));
return ele;
}
/**
* Create a TIFFdoubles node.
*/
static Node createTiffDoubles(final double ... doubles) {
final Element ele = createNode(TAG_GEOTIFF_DOUBLES);
for(final double d : doubles){
ele.appendChild(createTiffDouble(d));
}
return ele;
}
/**
* Create a TIFFdoubles node.
*/
static Node createTiffDoubles(final Collection<Double> doubles) {
final Element ele = createNode(TAG_GEOTIFF_DOUBLES);
for(final double d : doubles){
ele.appendChild(createTiffDouble(d));
}
return ele;
}
/**
* Create a TIFFAscii node.
*/
static Node createTiffAscii(final String ascii) {
final Element ele = createNode(TAG_GEOTIFF_ASCII);
ele.setAttribute(ATT_VALUE, ascii);
return ele;
}
/**
* Create a TIFFAsciis node.
*/
static Node createTiffAsciis(final String ... asciis) {
final Element ele = createNode(TAG_GEOTIFF_ASCIIS);
for(final String ascii : asciis){
ele.appendChild(createTiffAscii(ascii));
}
return ele;
}
/**
* Check if this metadata node contain a geoKeyDirectory node.
* If it's the case it is likely a geotiff metadata.
* @return true if metadata tree is a geotiff.
*/
public static boolean isGeoTiffTree(final Node candidate){
final Node imgFileDir = getNodeByLocalName(candidate,TAG_GEOTIFF_IFD);
if(imgFileDir == null) return false;
final Node geoKeyDir = getNodeByNumber(imgFileDir,TAG_GEO_KEY_DIRECTORY);
return geoKeyDir != null;
}
public static TIFFTag getGeoKeyDirectoryTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_GEO_KEY_DIRECTORY);
}
public static TIFFTag getGeoDoubleParamsTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_GEO_DOUBLE_PARAMS);
}
public static TIFFTag getGeoAsciiParamsTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_GEO_ASCII_PARAMS);
}
public static TIFFTag getModelPixelScaleTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_MODEL_PIXEL_SCALE);
}
public static TIFFTag getModelTiePointTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_MODEL_TIE_POINT);
}
public static TIFFTag getModelTransformationTag() {
return GeoTIFFTagSet.getInstance().getTag(TAG_MODEL_TRANSFORMATION);
}
}