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

📄 exifreader.java

📁 基于java平台的一个桌面相册,个人的电子相册...用eclipse开发的,管理并用线程做了一个浏览界面,按钮功能丰富...类似与三星的Digimax Master 可以查看相片的属性: 包括相片
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * EXIFExtractor.java
 *
 * This class based upon code from Jhead, a C program for extracting and
 * manipulating the Exif data within files written by Matthias Wandel.
 *   http://www.sentex.net/~mwandel/jhead/
 *
 * Jhead is public domain software - that is, you can do whatever you want
 * with it, and include it software that is licensed under the GNU or the
 * BSD license, or whatever other licence you choose, including proprietary
 * closed source licenses.  Similarly, I release this Java version under the
 * same license, though I do ask that you leave this header in tact.
 *
 * If you make modifications to this code that you think would benefit the
 * wider community, please send me a copy and I'll post it on my site.  Unlike
 * Jhead, this code (as it stands) only supports reading of Exif data - no
 * manipulation, and no thumbnail stuff.
 *
 * If you make use of this code, I'd appreciate hearing about it.
 *   drew.noakes@drewnoakes.com
 * Latest version of this software kept at
 *   http://drewnoakes.com/
 *
 * Created on 28 April 2002, 23:54
 * Modified 04 Aug 2002
 * - Renamed constants to be inline with changes to ExifTagValues interface
 * - Substituted usage of JDK 1.4 features (java.nio package)
 * Modified 29 Oct 2002 (v1.2)
 * - Proper traversing of Exif file structure and complete refactor & tidy of
 *   the codebase (a few unnoticed bugs removed)
 * - Reads makernote data for 6 families of camera (5 makes)
 * - Tags now stored in directories... use the IFD_* constants to refer to the
 *   image file directory you require (Exif, Interop, GPS and Makernote*) --
 *   this avoids collisions where two tags share the same code
 * - Takes componentCount of unknown tags into account
 * - Now understands GPS tags (thanks to Colin Briton for his help with this)
 * - Some other bug fixes, pointed out by users around the world.  Thanks!
 * Modified 27 Nov 2002 (v2.0)
 * - Renamed to ExifReader
 * - Moved to new package com.drew.metadata.exif
 * Modified since, however changes have not been logged.  See release notes for
 * library-wide modifications.
 */
package com.drew.metadata.exif;

import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.imaging.jpeg.JpegSegmentData;
import com.drew.imaging.jpeg.JpegSegmentReader;
import com.drew.lang.Rational;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.MetadataReader;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;

/**
 * Extracts Exif data from a JPEG header segment, providing information about the
 * camera/scanner/capture device (if available).  Information is encapsulated in
 * an <code>Metadata</code> object.
 * @author  Drew Noakes http://drewnoakes.com
 */
public class ExifReader implements MetadataReader
{
    /**
     * The JPEG segment as an array of bytes.
     */
    private final byte[] _data;

    /**
     * Represents the native byte ordering used in the JPEG segment.  If true,
     * then we're using Motorolla ordering (Big endian), else we're using Intel
     * ordering (Little endian).
     */
    private boolean _isMotorollaByteOrder;

    /**
     * Bean instance to store information about the image and camera/scanner/capture
     * device.
     */
    private Metadata _metadata;

    /**
     * The number of bytes used per format descriptor.
     */
    private static final int[] BYTES_PER_FORMAT = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};

    /**
     * The number of formats known.
     */
    private static final int MAX_FORMAT_CODE = 12;

    // Format types
    // Note: Cannot use the DataFormat enumeration in the case statement that uses these tags.
    //       Is there a better way?
    private static final int FMT_BYTE = 1;
    private static final int FMT_STRING = 2;
    private static final int FMT_USHORT = 3;
    private static final int FMT_ULONG = 4;
    private static final int FMT_URATIONAL = 5;
    private static final int FMT_SBYTE = 6;
    private static final int FMT_UNDEFINED = 7;
    private static final int FMT_SSHORT = 8;
    private static final int FMT_SLONG = 9;
    private static final int FMT_SRATIONAL = 10;
    private static final int FMT_SINGLE = 11;
    private static final int FMT_DOUBLE = 12;

    public static final int TAG_EXIF_OFFSET = 0x8769;
    public static final int TAG_INTEROP_OFFSET = 0xA005;
    public static final int TAG_GPS_INFO_OFFSET = 0x8825;
    public static final int TAG_MAKER_NOTE = 0x927C;

    public static final int TIFF_HEADER_START_OFFSET = 6;

    /**
     * Creates an ExifReader for a JpegSegmentData object.
     * @param segmentData
     */
    public ExifReader(JpegSegmentData segmentData)
    {
        this(segmentData.getSegment(JpegSegmentReader.SEGMENT_APP1));
    }

    /**
     * Creates an ExifReader for a Jpeg file.
     * @param file
     * @throws JpegProcessingException
     */
    public ExifReader(File file) throws JpegProcessingException
    {
        this(new JpegSegmentReader(file).readSegment(JpegSegmentReader.SEGMENT_APP1));
    }

    /**
     * Creates an ExifReader for a Jpeg stream.
     * @param is JPEG stream. Stream will be closed.
     */
    public ExifReader(InputStream is) throws JpegProcessingException
    {
        this(new JpegSegmentReader(is).readSegment(JpegSegmentReader.SEGMENT_APP1));
    }

    /**
     * Creates an ExifReader for the given JPEG header segment.
     */
    public ExifReader(byte[] data)
    {
        _data = data;
    }

    /**
     * Performs the Exif data extraction, returning a new instance of <code>Metadata</code>.
     */
    public Metadata extract()
    {
        return extract(new Metadata());
    }

    /**
     * Performs the Exif data extraction, adding found values to the specified
     * instance of <code>Metadata</code>.
     */
    public Metadata extract(Metadata metadata)
    {
        _metadata = metadata;
        if (_data==null)
            return _metadata;

        // once we know there's some data, create the directory and start working on it
        ExifDirectory directory = (ExifDirectory)_metadata.getDirectory(ExifDirectory.class);

        // check for the header length
        if (_data.length<=14) {
            directory.addError("Exif data segment must contain at least 14 bytes");
            return _metadata;
        }

        // check for the header preamble
        if (!"Exif\0\0".equals(new String(_data, 0, 6))) {
            directory.addError("Exif data segment doesn't begin with 'Exif'");
            return _metadata;
        }

        // this should be either "MM" or "II"
        String byteOrderIdentifier = new String(_data, 6, 2);
        if (!setByteOrder(byteOrderIdentifier)) {
            directory.addError("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier);
            return _metadata;
        }

        // Check the next two values for correctness.
        if (get16Bits(8)!=0x2a) {
            directory.addError("Invalid Exif start - should have 0x2A at offset 8 in Exif header");
            return _metadata;
        }

        int firstDirectoryOffset = get32Bits(10) + TIFF_HEADER_START_OFFSET;

        // David Ekholm sent an digital camera image that has this problem
        if (firstDirectoryOffset>=_data.length - 1) {
            directory.addError("First exif directory offset is beyond end of Exif data segment");
            // First directory normally starts 14 bytes in -- try it here and catch another error in the worst case
            firstDirectoryOffset = 14;
        }

        HashMap processedDirectoryOffsets = new HashMap();

        // 0th IFD (we merge with Exif IFD)
        processDirectory(directory, processedDirectoryOffsets, firstDirectoryOffset, TIFF_HEADER_START_OFFSET);

        // after the extraction process, if we have the correct tags, we may be able to store thumbnail information
        storeThumbnailBytes(directory, TIFF_HEADER_START_OFFSET);

        return _metadata;
    }

    private void storeThumbnailBytes(ExifDirectory exifDirectory, int tiffHeaderOffset)
    {
        if (!exifDirectory.containsTag(ExifDirectory.TAG_COMPRESSION))
        	return;

⌨️ 快捷键说明

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