Ignore:
Timestamp:
2013-08-09T18:05:11+02:00 (11 years ago)
Author:
bastiK
Message:

applied #8895 - Upgrade metadata-extractor to v. 2.6.4 (patch by ebourg)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/com/drew/metadata/iptc/IptcReader.java

    r4231 r6127  
    11/*
    2  * This is public domain software - that is, you can do whatever you want
    3  * with it, and include it software that is licensed under the GNU or the
    4  * BSD license, or whatever other licence you choose, including proprietary
    5  * closed source licenses.  I do ask that you leave this header in tact.
     2 * Copyright 2002-2012 Drew Noakes
    63 *
    7  * If you make modifications to this code that you think would benefit the
    8  * wider community, please send me a copy and I'll post it on my site.
     4 *    Licensed under the Apache License, Version 2.0 (the "License");
     5 *    you may not use this file except in compliance with the License.
     6 *    You may obtain a copy of the License at
    97 *
    10  * If you make use of this code, I'd appreciate hearing about it.
    11  *   drew@drewnoakes.com
    12  * Latest version of this software kept at
    13  *   http://drewnoakes.com/
     8 *        http://www.apache.org/licenses/LICENSE-2.0
    149 *
    15  * Created by dnoakes on 12-Nov-2002 19:00:03 using IntelliJ IDEA.
     10 *    Unless required by applicable law or agreed to in writing, software
     11 *    distributed under the License is distributed on an "AS IS" BASIS,
     12 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 *    See the License for the specific language governing permissions and
     14 *    limitations under the License.
     15 *
     16 * More information about this project is available at:
     17 *
     18 *    http://drewnoakes.com/code/exif/
     19 *    http://code.google.com/p/metadata-extractor/
    1620 */
    1721package com.drew.metadata.iptc;
    1822
    19 import com.drew.imaging.jpeg.JpegProcessingException;
    20 import com.drew.imaging.jpeg.JpegSegmentReader;
     23import com.drew.lang.BufferBoundsException;
     24import com.drew.lang.BufferReader;
     25import com.drew.lang.annotations.NotNull;
    2126import com.drew.metadata.Directory;
    2227import com.drew.metadata.Metadata;
    23 import com.drew.metadata.MetadataException;
    2428import com.drew.metadata.MetadataReader;
    2529
    26 import java.io.File;
    27 import java.io.InputStream;
    2830import java.util.Date;
    2931
    3032/**
     33 * Decodes IPTC binary data, populating a <code>Metadata</code> object with tag values in an <code>IptcDirectory</code>.
    3134 *
     35 * @author Drew Noakes http://drewnoakes.com
    3236 */
    3337public class IptcReader implements MetadataReader
    3438{
     39    // TODO consider breaking the IPTC section up into multiple directories and providing segregation of each IPTC directory
    3540/*
    3641    public static final int DIRECTORY_IPTC = 2;
     
    4651    public static final int POST_DATA_RECORD = 9;
    4752*/
    48     /**
    49      * The Iptc data segment.
    50      */
    51     private final byte[] _data;
    5253
    53     /**
    54      * Creates a new IptcReader for the specified Jpeg jpegFile.
    55      */
    56     public IptcReader(File jpegFile) throws JpegProcessingException
     54    /** Performs the IPTC data extraction, adding found values to the specified instance of <code>Metadata</code>. */
     55    public void extract(@NotNull final BufferReader reader, @NotNull final Metadata metadata)
    5756    {
    58         this(new JpegSegmentReader(jpegFile).readSegment(JpegSegmentReader.SEGMENT_APPD));
    59     }
     57        IptcDirectory directory = metadata.getOrCreateDirectory(IptcDirectory.class);
    6058
    61     /** Creates an IptcReader for a JPEG stream.
    62      *
    63      * @param is JPEG stream. Stream will be closed.
    64      */
    65     public IptcReader(InputStream is) throws JpegProcessingException
    66     {
    67         this(new JpegSegmentReader(is).readSegment(JpegSegmentReader.SEGMENT_APPD));
    68     }
     59        int offset = 0;
    6960
    70     public IptcReader(byte[] data)
    71     {
    72         _data = data;
    73     }
    74 
    75     /**
    76      * Performs the Exif data extraction, returning a new instance of <code>Metadata</code>.
    77      */
    78     public Metadata extract()
    79     {
    80         return extract(new Metadata());
    81     }
    82 
    83     /**
    84      * Performs the Exif data extraction, adding found values to the specified
    85      * instance of <code>Metadata</code>.
    86      */
    87     public Metadata extract(Metadata metadata)
    88     {
    89         if (_data == null) {
    90             return metadata;
     61/*
     62        // find start-of-segment marker (potentially need to skip some ASCII photoshop header info)
     63        try {
     64            while (offset < data.length - 1 && reader.getUInt16(offset) != 0x1c01 && reader.getUInt16(offset) != 0x1c02)
     65                offset++;
     66        } catch (BufferBoundsException e) {
     67            directory.addError("Couldn't find start of IPTC data (invalid segment)");
     68            return;
    9169        }
    92 
    93         Directory directory = metadata.getDirectory(IptcDirectory.class);
    94 
    95         // find start of data
    96         int offset = 0;
    97         try {
    98             while (offset < _data.length - 1 && get32Bits(offset) != 0x1c02) {
    99                 offset++;
    100             }
    101         } catch (MetadataException e) {
    102             directory.addError("Couldn't find start of Iptc data (invalid segment)");
    103             return metadata;
    104         }
     70*/
    10571
    10672        // for each tag
    107         while (offset < _data.length) {
     73        while (offset < reader.getLength()) {
     74
    10875            // identifies start of a tag
    109             if (_data[offset] != 0x1c) {
     76            short startByte;
     77            try {
     78                startByte = reader.getUInt8(offset);
     79            } catch (BufferBoundsException e) {
     80                directory.addError("Unable to read starting byte of IPTC tag");
    11081                break;
    11182            }
     83
     84            if (startByte != 0x1c) {
     85                directory.addError("Invalid start to IPTC tag");
     86                break;
     87            }
     88
    11289            // we need at least five bytes left to read a tag
    113             if ((offset + 5) >= _data.length) {
     90            if (offset + 5 >= reader.getLength()) {
     91                directory.addError("Too few bytes remain for a valid IPTC tag");
    11492                break;
    11593            }
     
    12199            int tagByteCount;
    122100            try {
    123                 directoryType = _data[offset++];
    124                 tagType = _data[offset++];
    125                 tagByteCount = get32Bits(offset);
    126             } catch (MetadataException e) {
    127                 directory.addError("Iptc data segment ended mid-way through tag descriptor");
    128                 return metadata;
     101                directoryType = reader.getUInt8(offset++);
     102                tagType = reader.getUInt8(offset++);
     103                tagByteCount = reader.getUInt16(offset);
     104                offset += 2;
     105            } catch (BufferBoundsException e) {
     106                directory.addError("IPTC data segment ended mid-way through tag descriptor");
     107                return;
    129108            }
    130             offset += 2;
    131             if ((offset + tagByteCount) > _data.length) {
    132                 directory.addError("data for tag extends beyond end of iptc segment");
     109
     110            if (offset + tagByteCount > reader.getLength()) {
     111                directory.addError("Data for tag extends beyond end of IPTC segment");
    133112                break;
    134113            }
    135114
    136             processTag(directory, directoryType, tagType, offset, tagByteCount);
     115            try {
     116                processTag(reader, directory, directoryType, tagType, offset, tagByteCount);
     117            } catch (BufferBoundsException e) {
     118                directory.addError("Error processing IPTC tag");
     119                break;
     120            }
     121
    137122            offset += tagByteCount;
    138123        }
    139 
    140         return metadata;
    141124    }
    142125
    143     /**
    144      * Returns an int calculated from two bytes of data at the specified offset (MSB, LSB).
    145      * @param offset position within the data buffer to read first byte
    146      * @return the 32 bit int value, between 0x0000 and 0xFFFF
    147      */
    148     private int get32Bits(int offset) throws MetadataException
    149     {
    150         if (offset >= _data.length) {
    151             throw new MetadataException("Attempt to read bytes from outside Iptc data buffer");
    152         }
    153         return ((_data[offset] & 255) << 8) | (_data[offset + 1] & 255);
    154     }
    155 
    156     /**
    157      * This method serves as marsheller of objects for dataset. It converts from IPTC
    158      * octets to relevant java object.
    159      */
    160     private void processTag(Directory directory, int directoryType, int tagType, int offset, int tagByteCount)
     126    private void processTag(@NotNull BufferReader reader, @NotNull Directory directory, int directoryType, int tagType, int offset, int tagByteCount) throws BufferBoundsException
    161127    {
    162128        int tagIdentifier = tagType | (directoryType << 8);
    163129
    164130        switch (tagIdentifier) {
    165             case IptcDirectory.TAG_RECORD_VERSION:
     131            case IptcDirectory.TAG_APPLICATION_RECORD_VERSION:
    166132                // short
    167                 short shortValue = (short)((_data[offset] << 8) | _data[offset + 1]);
     133                int shortValue = reader.getUInt16(offset);
    168134                directory.setInt(tagIdentifier, shortValue);
    169135                return;
    170136            case IptcDirectory.TAG_URGENCY:
    171137                // byte
    172                 directory.setInt(tagIdentifier, _data[offset]);
     138                directory.setInt(tagIdentifier, reader.getUInt8(offset));
    173139                return;
    174140            case IptcDirectory.TAG_RELEASE_DATE:
     
    176142                // Date object
    177143                if (tagByteCount >= 8) {
    178                     String dateStr = new String(_data, offset, tagByteCount);
     144                    String dateStr = reader.getString(offset, tagByteCount);
    179145                    try {
    180146                        int year = Integer.parseInt(dateStr.substring(0, 4));
    181147                        int month = Integer.parseInt(dateStr.substring(4, 6)) - 1;
    182148                        int day = Integer.parseInt(dateStr.substring(6, 8));
    183                         Date date = (new java.util.GregorianCalendar(year, month, day)).getTime();
     149                        Date date = new java.util.GregorianCalendar(year, month, day).getTime();
    184150                        directory.setDate(tagIdentifier, date);
    185151                        return;
     
    194160                // fall through
    195161        }
    196         // If no special handling by now, treat it as a string
     162
     163        // If we haven't returned yet, treat it as a string
    197164        String str;
    198165        if (tagByteCount < 1) {
    199166            str = "";
    200167        } else {
    201             str = new String(_data, offset, tagByteCount);
     168            str = reader.getString(offset, tagByteCount, System.getProperty("file.encoding")); // "ISO-8859-1"
    202169        }
     170
    203171        if (directory.containsTag(tagIdentifier)) {
    204             String[] oldStrings;
     172            // this fancy string[] business avoids using an ArrayList for performance reasons
     173            String[] oldStrings = directory.getStringArray(tagIdentifier);
    205174            String[] newStrings;
    206             try {
    207                 oldStrings = directory.getStringArray(tagIdentifier);
    208             } catch (MetadataException e) {
    209                 oldStrings = null;
    210             }
    211175            if (oldStrings == null) {
    212176                newStrings = new String[1];
    213177            } else {
    214178                newStrings = new String[oldStrings.length + 1];
    215                 for (int i = 0; i < oldStrings.length; i++) {
    216                     newStrings[i] = oldStrings[i];
    217                 }
     179                System.arraycopy(oldStrings, 0, newStrings, 0, oldStrings.length);
    218180            }
    219181            newStrings[newStrings.length - 1] = str;
Note: See TracChangeset for help on using the changeset viewer.