@@ -1640,34 +1640,29 @@ public IIOMetadataNode[] getMetadataByTagName(String tagName){
16401640//** MetadataParser Class
16411641//******************************************************************************
16421642/**
1643- * Class used to decode EXIF and IPTC metadata. The MetadataParser is based
1644- * on two classes developed by Norman Walsh and released under the W3C open
1645- * source license. The original classes can be found in the W3C Jigsaw
1646- * project ("Exif.java" and "ExifData.java" in the "org.w3c.tools.jpeg"
1647- * package).
1648- * <br/>
1649- * You may use this code in any open source or commercial project provided
1650- * that you publish the standard W3C Software Notice and License Agreement.
1643+ * Used to decode EXIF and IPTC metadata. Adapted from 2 classes developed by
1644+ * Norman Walsh and released under the W3C open source license. The original
1645+ * exif classes can be found in the W3C Jigsaw project in the
1646+ * org.w3c.tools.jpeg package.
16511647 *
1652- * @version $Revision: 1.1 $
1653- * @author Norman Walsh
1654- * @copyright Copyright (c) 2003 Norman Walsh
1648+ * @author Norman Walsh
1649+ * @copyright Copyright (c) 2003 Norman Walsh
16551650 ******************************************************************************/
16561651
16571652private class MetadataParser {
16581653
16591654// Implementation notes:
1660- // (1) Unknown/Undefined values are all Base64 encoded.
1661- // (2) Unsigned integers are treated as signed ints (should be longs). Note
1662- // that its pretty rare to see a EXIF unsigned value too large to represent
1663- // in a Java int.
1664- // (3) Added logic to parse GPS Info using the GPS IFD offset value (tag 34853,
1655+ // (1) Merged Version 1.1 of the "Exif.java" and "ExifData.java" classes.
1656+ // (2) Added new IPTC metadata parser.
1657+ // (3) All Unknown/Undefined EXIF fields are Base64 encoded. Need to do the
1658+ // same for unknown IPTC fields.
1659+ // (4) All unsigned integers are treated as signed ints (should be longs).
1660+ // (5) Added logic to parse GPS Info using the GPS IFD offset value (tag 34853,
16651661// hex 0x8825).
1666- // (4 ) Added logic to parse an array of rational numbers (e.g. GPS metadata).
1667- // (5 ) Improved performance in the parseExif() method by serializing only the
1662+ // (6 ) Added logic to parse an array of rational numbers (e.g. GPS metadata).
1663+ // (7 ) Improved performance in the parseExif() method by serializing only the
16681664// first 8 characters into a string (vs the entire EXIF byte array).
1669- // (6) TODO: Need to come up with a clever scheme to parse MakerNotes.
1670-
1665+ // (8) TODO: Need to come up with a clever scheme to parse MakerNotes.
16711666
16721667 private final int bytesPerFormat [] = { 0 , 1 , 1 , 2 , 4 , 8 , 1 ,
16731668 1 , 2 , 4 , 8 , 4 , 8 };
@@ -1699,8 +1694,8 @@ private class MetadataParser {
16991694
17001695 public MetadataParser (byte [] data , int marker ) {
17011696 switch (marker ) {
1702- case 0xED : parseIptc (data );
1703- case 0xE1 : parseExif (data );
1697+ case 0xED : parseIptc (data ); break ;
1698+ case 0xE1 : parseExif (data ); break ;
17041699 }
17051700
17061701 data = null ;
@@ -1828,8 +1823,6 @@ private void processExifDir(int dirStart, int offsetBase, HashMap<Integer, Strin
18281823
18291824
18301825 int numEntries = get16u (dirStart );
1831- //System.err.println("EXIF: numEntries: " + numEntries);
1832-
18331826 for (int de = 0 ; de < numEntries ; de ++) {
18341827 int dirOffset = dirStart + 2 + (12 * de );
18351828
@@ -1888,116 +1881,60 @@ private void processExifDir(int dirStart, int offsetBase, HashMap<Integer, Strin
18881881 //processExifDir(0, 6);
18891882
18901883 //}
1891-
1892-
1884+
18931885 else {
18941886
18951887 switch (format ) {
1896- case FMT_UNDEFINED :
1897- assignUndefined (tag , tags , valueOffset , byteCount );
1898- break ;
18991888 case FMT_STRING :
1900- assignString (tag , tags , valueOffset , byteCount );
1889+ String value = getString (valueOffset , byteCount );
1890+ if (value !=null ) tags .put (tag , value );
19011891 break ;
19021892 case FMT_SBYTE :
1903- assignSByte (tag , tags , valueOffset );
1904- break ;
19051893 case FMT_BYTE :
1906- assignByte (tag , tags , valueOffset );
1907- break ;
19081894 case FMT_USHORT :
1909- assignUShort (tag , tags , valueOffset );
1910- break ;
19111895 case FMT_SSHORT :
1912- assignSShort (tag , tags , valueOffset );
1913- break ;
19141896 case FMT_ULONG :
1915- assignULong (tag , tags , valueOffset );
1916- break ;
19171897 case FMT_SLONG :
1918- assignSLong (tag , tags , valueOffset );
1898+ tags . put (tag , "" + ( int ) getDouble ( format , valueOffset ) );
19191899 break ;
19201900 case FMT_URATIONAL :
19211901 case FMT_SRATIONAL :
19221902
19231903 if (components >1 ) {
19241904
19251905 //Create a string representing an array of rational numbers
1926- StringBuffer rationals = new StringBuffer ();
1927- rationals .append ("[" );
1928- for (int i = 0 ; i < components ; i ++){
1929- assignRational (tag , tags , valueOffset + (8 * i ));
1930- rationals .append (tags .get (tag ));
1931- if (i < components -1 ) rationals .append ("," );
1906+ StringBuffer str = new StringBuffer ();
1907+ str .append ("[" );
1908+ for (int i =0 ; i <components ; i ++){
1909+ str .append ( getRational (valueOffset + (8 * i )) );
1910+ if (i <components -1 ) str .append ("," );
19321911 }
1933- rationals .append ("]" );
1934- tags .put (tag , rationals .toString ());
1912+ str .append ("]" );
1913+ tags .put (tag , str .toString ());
19351914 }
19361915 else {
1937- assignRational (tag , tags , valueOffset );
1916+ tags . put (tag , getRational ( valueOffset ) );
19381917 }
19391918 break ;
19401919
1941-
1942-
1943- default :
1944- //System.err.println("Unknown format " + format +
1945- // " for " + tagName) ;
1920+
1921+ default : //including FMT_UNDEFINED
1922+ String result = javaxt . utils . Base64 . encodeBytes ( getUndefined ( valueOffset , byteCount ));
1923+ if ( result != null && result . length ()> 0 ) tags . put ( tag , result );
1924+ break ;
19461925 }
19471926
19481927 }
19491928 }
19501929 }
19511930
1952-
1953-
1954- private void assignUndefined (int tag , HashMap <Integer , String > tags , int offset , int length ) {
1955- //System.out.println("0x" + Integer.toHexString(tagName));
1956-
1957- String result = getUndefined (offset , length );
1958- if (!"" .equals (result )) {
1959- tags .put (tag , result );
1960- }
1961- }
1962-
1963- private void assignString (int tag , HashMap <Integer , String > tags , int offset , int length ) {
1964- String result = getString (offset , length );
1965- if (!"" .equals (result )) {
1966- tags .put (tag , result );
1967- }
1968- }
1969-
1970- private void assignSByte (int tag , HashMap <Integer , String > tags , int offset ) {
1971- int result = (int ) convertAnyValue (FMT_SBYTE , offset );
1972- tags .put (tag , "" + result );
1973- }
1974-
1975- private void assignByte (int tag , HashMap <Integer , String > tags , int offset ) {
1976- int result = (int ) convertAnyValue (FMT_BYTE , offset );
1977- tags .put (tag , "" + result );
1978- }
1979-
1980- private void assignUShort (int tag , HashMap <Integer , String > tags , int offset ) {
1981- int result = (int ) convertAnyValue (FMT_USHORT , offset );
1982- tags .put (tag , "" + result );
1983- }
1984-
1985- private void assignSShort (int tag , HashMap <Integer , String > tags , int offset ) {
1986- int result = (int ) convertAnyValue (FMT_SSHORT , offset );
1987- tags .put (tag , "" + result );
1988- }
1989-
1990- private void assignULong (int tag , HashMap <Integer , String > tags , int offset ) {
1991- int result = (int ) convertAnyValue (FMT_ULONG , offset );
1992- tags .put (tag , "" + result );
1993- }
1994-
1995- private void assignSLong (int tag , HashMap <Integer , String > tags , int offset ) {
1996- int result = (int ) convertAnyValue (FMT_SLONG , offset );
1997- tags .put (tag , "" + result );
1998- }
1999-
2000- private void assignRational (int tag , HashMap <Integer , String > tags , int offset ) {
1931+ //**************************************************************************
1932+ //** getRational
1933+ //**************************************************************************
1934+ /** Returns a string representation of a rational number (numerator and
1935+ * denominator separated with a "/" character).
1936+ */
1937+ private String getRational (int offset ) {
20011938 int num = get32s (offset );
20021939 int den = get32s (offset + 4 );
20031940 String result = "" ;
@@ -2030,16 +1967,10 @@ private void assignRational(int tag, HashMap<Integer, String> tags, int offset)
20301967 } else {
20311968 result = "" + num + "/" + den ;
20321969 }
2033-
2034-
2035- tags .put (tag , "" + result );
1970+ return result ;
20361971 }
20371972
20381973 private int get16s (int offset ) {
2039- if (data == null ) {
2040- return 0 ;
2041- }
2042-
20431974 int hi , lo ;
20441975
20451976 if (intelOrder ) {
@@ -2057,20 +1988,11 @@ private int get16s(int offset) {
20571988 }
20581989
20591990 private int get16u (int offset ) {
2060- if (data == null ) {
2061- return 0 ;
2062- }
2063-
20641991 int value = get16s (offset );
2065- value = value & 0xFFFF ;
2066- return value ;
1992+ return value & 0xFFFF ;
20671993 }
20681994
20691995 private int get32s (int offset ) {
2070- if (data == null ) {
2071- return 0 ;
2072- }
2073-
20741996 int n1 , n2 , n3 , n4 ;
20751997
20761998 if (intelOrder ) {
@@ -2085,98 +2007,56 @@ private int get32s(int offset) {
20852007 n4 = data [offset + 3 ] & 0xFF ;
20862008 }
20872009
2088- int value = (n1 << 24 ) + (n2 << 16 ) + (n3 << 8 ) + n4 ;
2089-
2090- return value ;
2010+ return (n1 << 24 ) + (n2 << 16 ) + (n3 << 8 ) + n4 ;
20912011 }
20922012
20932013 private int get32u (int offset ) {
2094- if (data == null ) {
2095- return 0 ;
2096- }
2097-
2098- // I don't know how to represent an unsigned in Java!
2099- return get32s (offset );
2014+ return get32s (offset ); //Should probably return a long instead...
21002015 }
21012016
2102- /*
2103- private byte[] getBytes(int offset, int length) {
2104- if (data == null || length == 0) {
2105- return null;
2106- }
2107-
2108- byte[] raw = new byte[length];
2109- for (int count = offset; length > 0; count++, length--) {
2110- raw[count - offset] = data[count];
2111- }
2112-
2113- return raw;
2114- }
2115- */
2116-
2117-
2118- private String getUndefined (int offset , int length ) {
2119- //return getString(offset, length, false);
2120- return javaxt .utils .Base64 .encodeBytes (data , offset , length );
2017+ private byte [] getUndefined (int offset , int length ) {
2018+ return java .util .Arrays .copyOfRange (data , offset , offset +length );
21212019 }
21222020
21232021 private String getString (int offset , int length ) {
2124- if (data == null ) {
2125- return "" ;
2126- }
2127-
21282022 try {
21292023 return new String (data , offset , length , "UTF-8" ).trim ();
21302024 }
21312025 catch (Exception e ){
2132- return "" ;
2026+ return null ;
21332027 }
21342028 }
21352029
2136- private double convertAnyValue ( int format , int offset ) {
2137- if ( data == null ) {
2138- return 0.0 ;
2139- }
2140-
2141- double value = 0.0 ;
2142-
2030+ //**************************************************************************
2031+ //** getDouble
2032+ //**************************************************************************
2033+ /** Used convert a byte into a double. Note that this method used to be
2034+ * called convertAnyValue().
2035+ */
2036+ private double getDouble ( int format , int offset ) {
21432037 switch (format ) {
2144- case FMT_SBYTE :
2145- value = data [offset ];
2146- break ;
2147- case FMT_BYTE :
2148- int iValue = data [offset ];
2149- iValue = iValue & 0xFF ;
2150- value = iValue ;
2151- break ;
2152- case FMT_USHORT :
2153- value = get16u (offset );
2154- break ;
2155- case FMT_ULONG :
2156- value = get32u (offset );
2157- break ;
2158- case FMT_URATIONAL :
2159- case FMT_SRATIONAL :
2160- int num = get32s (offset );
2161- int den = get32s (offset + 4 );
2162-
2163- if (den == 0 ) {
2164- value = 0 ;
2165- } else {
2166- value = (double ) num / (double ) den ;
2167- }
2168- break ;
2169- case FMT_SSHORT :
2170- value = get16s (offset );
2171- break ;
2172- case FMT_SLONG :
2173- value = get32s (offset );
2174- break ;
2175- default :
2176- //System.err.println("Unexpected number format: " + format);
2177- }
2178-
2179- return value ;
2038+ case FMT_SBYTE :
2039+ return data [offset ];
2040+ case FMT_BYTE :
2041+ int iValue = data [offset ];
2042+ return iValue & 0xFF ;
2043+ case FMT_USHORT :
2044+ return get16u (offset );
2045+ case FMT_ULONG :
2046+ return get32u (offset );
2047+ case FMT_URATIONAL :
2048+ case FMT_SRATIONAL :
2049+ int num = get32s (offset );
2050+ int den = get32s (offset + 4 );
2051+ if (den == 0 ) return 0 ;
2052+ else return (double ) num / (double ) den ;
2053+ case FMT_SSHORT :
2054+ return get16s (offset );
2055+ case FMT_SLONG :
2056+ return get32s (offset );
2057+ default :
2058+ return 0.0 ;
2059+ }
21802060 }
21812061}
21822062
0 commit comments