⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exif.java

📁 很棒的web服务器源代码
💻 JAVA
字号:
// Exif.java// $Id: Exif.java,v 1.1 2003/07/23 12:08:01 ylafon Exp $// Copyright (c) 2003 Norman Walsh// Please first read the full copyright statement in file COPYRIGHTpackage org.w3c.tools.jpeg;import java.util.Hashtable;/** * An API for accessing EXIF encoded information in a JPEG file. * * <p>JPEG images are stored in a tagged format reminiscent of TIFF files. * Each component of the image is identified with a tag number and a size. * This allows applications that read JPEG files to skip over information * that they don't understand.</p> * * <p>Additional resources:</p> * <ul> * <li>Official standards, http://www.exif.org/specifications.html</li> * <li>TsuruZoh Tachibanaya's excellent description, * http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html * </li> * <li>Matthias Wandel's JHead, http://www.sentex.net/~mwandel/jhead * </ul> * * <p>This class treats a byte array as a JPEG image and parses the tags * searching for EXIF data. EXIF data is also tagged. Based on information * provided by the caller, this class builds a hash of EXIF data and * makes it available to the caller.</p> * * <p>Most simple EXIF values are tagged with both their identity and their * format. For example, ExposureTime (0x829A) is a rational number and * this class can extract that value. However, some fields are of "unknown" * format. If you decode one of these, you can add a special purpose decode * for that field by associating the name of the decoder class with the * field name. For example, my Nikon CoolPix 950 includes a MakerNote (0x927C) * field that's tagged "unknown" format. Using information from TsuruZoh's * page, I've built a decoder for that field and added it as an example.</p> * * <p>In addition to the tagged data, JPEG images have five intrinisic * properties: height, width, the compression algorithm used, the number of  * bits used to store each pixel value, and the number of color components. * This class allows the caller to unify those intrinsic components with the * tagged data.</p> * * <p>In an effort to be flexible without requiring users to change the * source, a fair bit of setup is needed to use this class.</p> * * <p>The caller must:</p> * * <ol> * <li>Construct an Exif object, <code>exif = new Exif()</code>.</li> * <li>Associate names with each of the tags of interest, *     <code>exif.addTag(<em>nnn</em>, "<em>name</em>")</code>.</li> * <li>Associate names with the intrinsic values: *   <ul> *     <li><code>exif.addHeight("<em>name</em>")</code> *     <li><code>exif.addWidth("<em>name</em>")</code> *     <li><code>exif.addCompression("<em>name</em>")</code> *     <li><code>exif.addNumberOfColorComponents("<em>name</em>")</code> *     <li><code>exif.addBitsPerPixel("<em>name</em>")</code> *   </ul> * </li> * <li>Finally, the caller may associate a decoder with specific fields: * <code>exif.addDecoder("<em>name</em>", "<em>java.class.name</em>")</code>. * </li> * </ol> * * <p>Having setup the exif object, it can be passed to JpegHeaders to be  * filled in when the JPEG file is parsed.</p> * * <p>The caller must also explicitly set the intrinsic values since they do * not come from the EXIF data.</p> * * <p>After parsing the JPEG, call <code>exif.getTags()</code> to get back the * has of name/value pairs.</p> * * @version $Revision: 1.1 $ * @author  Norman Walsh * @see ExifData * @see TagDecoder * @see JpegHeaders */public class Exif {    private static final int TAG_EXIF_OFFSET = 0x8769;    private static final int TAG_INTEROP_OFFSET = 0xa005;    private Hashtable tags = new Hashtable();    private Hashtable exif = new Hashtable();    private Hashtable decoder = new Hashtable();    private ExifData data = null;    private boolean intelOrder = false;    private String tagHeight = null;    private String tagWidth = null;    private String tagComp = null;    private String tagBPP = null;    private String tagNumCC = null;    public void parseExif(byte[] exifData) {	data = new ExifData(exifData);	if (!data.isExifData()) {	    return;	}	int firstOffset = data.get32u(10);	processExifDir(6+firstOffset, 6);    }    public void setHeight(int height) {	if (tagHeight != null) {	    exif.put(tagHeight, ""+height);	}    }    public void setWidth(int width) {	if (tagWidth != null) {	    exif.put(tagWidth, ""+width);	}    }    public void setCompression(String comp) {	if (tagComp != null) {	    exif.put(tagComp, comp);	}    }    public void setBPP(int bitsPP) {	if (tagBPP != null) {	    exif.put(tagBPP, ""+bitsPP);	}    }    public void setNumCC(int numCC) {	if (tagNumCC != null) {	    exif.put(tagNumCC, ""+numCC);	}    }    public void addHeight(String name) {	tagHeight = name;    }    public void addWidth(String name) {	tagWidth = name;    }    public void addCompression(String name) {	tagComp = name;    }    public void addBitsPerPixel(String name) {	tagBPP = name;    }    public void addNumberOfColorComponents(String name) {	tagNumCC = name;    }    public void addTag(int tag, String tagName) {	tags.put(new Integer(tag), tagName);    }    public void addDecoder(String name, String className) {	decoder.put(name, className);    }    public Hashtable getTags() {	return exif;    }    protected void processExifDir(int dirStart,				  int offsetBase) {	int numEntries = data.get16u(dirStart);	//System.err.println("EXIF: numEntries: " + numEntries);	for (int de = 0; de < numEntries; de++) {	    int dirOffset = dirStart + 2 + (12 * de);	    int tag = data.get16u(dirOffset);	    int format = data.get16u(dirOffset+2);	    int components = data.get32u(dirOffset+4);	    //System.err.println("EXIF: entry: 0x" + Integer.toHexString(tag)	    //		 + " " + format	    //		 + " " + components);	    if (format < 0 || format > data.NUM_FORMATS) {		System.err.println("Bad number of formats in EXIF dir: " +				   format);		return;	    }	    int byteCount = components * ExifData.bytesPerFormat[format];	    int valueOffset = dirOffset + 8;	    if (byteCount > 4) {		int offsetVal = data.get32u(dirOffset+8);		valueOffset = offsetBase + offsetVal;	    }	    //System.err.println("valueOffset: " + valueOffset + 	    //                                     " byteCount: " + byteCount);	    Integer iTag = new Integer(tag);	    if (tag == TAG_EXIF_OFFSET || tag == TAG_INTEROP_OFFSET) {		int subdirOffset = data.get32u(valueOffset);		//System.err.println("offset: " + subdirOffset+		//                                ":"+offsetBase+subdirOffset);		processExifDir(offsetBase+subdirOffset, offsetBase);	    } else {		String tagName = "BugBugBug";		boolean usedTag = false;		if (tags.containsKey(iTag)) {		    tagName = (String) tags.get(iTag);		    usedTag = true;		} else {		    tagName = ":unknown0x" + 			                  Integer.toHexString(iTag.intValue());		}		if (decoder.containsKey(tagName)) {		    String className = (String) decoder.get(tagName);		    TagDecoder decoder = null;		    try {			decoder = (TagDecoder) 			                Class.forName(className).newInstance();		    } catch (ClassNotFoundException cnfe) {			System.err.println("Class not found: " + className);		    } catch (InstantiationException cnfe) {			System.err.println("Failed to instantiate " +					   className);		    } catch (IllegalAccessException cnfe) {			System.err.println("Illegal access instantiating " +					   className);		    } catch (ClassCastException cnfe) {			System.err.println("Class " + className + 					   " is not a TagDecoder");		    }		    if (decoder != null) {			decoder.decode(exif, data, format, valueOffset, 				       byteCount);		    }		} else {		    switch (format) {		    case ExifData.FMT_UNDEFINED:			assignUndefined(tagName, valueOffset, byteCount);			break;		    case ExifData.FMT_STRING:			assignString(tagName, valueOffset, byteCount);			break;		    case ExifData.FMT_SBYTE:			assignSByte(tagName, valueOffset);			break;		    case ExifData.FMT_BYTE:			assignByte(tagName, valueOffset);			break;		    case ExifData.FMT_USHORT:			assignUShort(tagName, valueOffset);			break;		    case ExifData.FMT_SSHORT:			assignSShort(tagName, valueOffset);			break;		    case ExifData.FMT_ULONG:			assignULong(tagName, valueOffset);			break;		    case ExifData.FMT_SLONG:			assignSLong(tagName, valueOffset);			break;		    case ExifData.FMT_URATIONAL:		    case ExifData.FMT_SRATIONAL:			assignRational(tagName, valueOffset);			break;		    default:			//System.err.println("Unknown format " + format + 			//                   " for " + tagName);		    }		}	    }	}    }    protected void assignUndefined(String tagName, int offset, int length) {	String result = data.getUndefined(offset, length);	if (!"".equals(result)) {	    exif.put(tagName, result);	}    }    protected void assignString(String tagName, int offset, int length) {	String result = data.getString(offset, length);	if (!"".equals(result)) {	    exif.put(tagName, result);	}    }    protected void assignSByte(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_SBYTE, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignByte(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_BYTE, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignUShort(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_USHORT, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignSShort(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_SSHORT, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignULong(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_ULONG, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignSLong(String tagName, int offset) {	int result = (int) data.convertAnyValue(ExifData.FMT_SLONG, offset);	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }    protected void assignRational(String tagName, int offset) {	int num = data.get32s(offset);	int den = data.get32s(offset+4);	String result = "";	// This is a bit silly, I really ought to find a real GCD algorithm	if (num % 10 == 0 && den % 10 == 0) {	    num = num / 10;	    den = den / 10;	}	if (num % 5 == 0 && den % 5 == 0) {	    num = num / 5;	    den = den / 5;	}	if (num % 3 == 0 && den % 3 == 0) {	    num = num / 3;	    den = den / 3;	}	if (num % 2 == 0 && den % 2 == 0) {	    num = num / 2;	    den = den / 2;	}	if (den == 0) {	    result = "0";	} else if (den == 1) {	    result = "" + num; // "" + int sure looks ugly...	} else {	    result = "" + num + "/" + den;	}	//System.err.println("\t" + tagName + ": " + result);	exif.put(tagName, ""+result);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -