Ignore:
Timestamp:
2019-07-07T01:56:46+02:00 (5 years ago)
Author:
Don-vip
Message:

see #17848 - update to metadata-extractor 2.12.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/com/drew/metadata/exif/ExifTiffHandler.java

    r13061 r15217  
    11/*
    2  * Copyright 2002-2017 Drew Noakes
     2 * Copyright 2002-2019 Drew Noakes and contributors
    33 *
    44 *    Licensed under the Apache License, Version 2.0 (the "License");
     
    3030import com.drew.imaging.tiff.TiffProcessingException;
    3131import com.drew.imaging.tiff.TiffReader;
     32import com.drew.lang.BufferBoundsException;
    3233import com.drew.lang.Charsets;
    3334import com.drew.lang.RandomAccessReader;
     
    3839import com.drew.metadata.Metadata;
    3940import com.drew.metadata.StringValue;
    40 import com.drew.metadata.exif.makernotes.*;
     41import com.drew.metadata.exif.makernotes.AppleMakernoteDirectory;
     42import com.drew.metadata.exif.makernotes.CanonMakernoteDirectory;
     43import com.drew.metadata.exif.makernotes.CasioType1MakernoteDirectory;
     44import com.drew.metadata.exif.makernotes.CasioType2MakernoteDirectory;
     45import com.drew.metadata.exif.makernotes.FujifilmMakernoteDirectory;
     46import com.drew.metadata.exif.makernotes.KodakMakernoteDirectory;
     47import com.drew.metadata.exif.makernotes.KyoceraMakernoteDirectory;
     48import com.drew.metadata.exif.makernotes.LeicaMakernoteDirectory;
     49import com.drew.metadata.exif.makernotes.LeicaType5MakernoteDirectory;
     50import com.drew.metadata.exif.makernotes.NikonType1MakernoteDirectory;
     51import com.drew.metadata.exif.makernotes.NikonType2MakernoteDirectory;
     52import com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory;
     53import com.drew.metadata.exif.makernotes.OlympusEquipmentMakernoteDirectory;
     54import com.drew.metadata.exif.makernotes.OlympusFocusInfoMakernoteDirectory;
     55import com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory;
     56import com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory;
     57import com.drew.metadata.exif.makernotes.OlympusRawDevelopment2MakernoteDirectory;
     58import com.drew.metadata.exif.makernotes.OlympusRawDevelopmentMakernoteDirectory;
     59import com.drew.metadata.exif.makernotes.OlympusRawInfoMakernoteDirectory;
     60import com.drew.metadata.exif.makernotes.PanasonicMakernoteDirectory;
     61import com.drew.metadata.exif.makernotes.PentaxMakernoteDirectory;
     62import com.drew.metadata.exif.makernotes.ReconyxHyperFireMakernoteDirectory;
     63import com.drew.metadata.exif.makernotes.ReconyxUltraFireMakernoteDirectory;
     64import com.drew.metadata.exif.makernotes.RicohMakernoteDirectory;
     65import com.drew.metadata.exif.makernotes.SamsungType2MakernoteDirectory;
     66import com.drew.metadata.exif.makernotes.SanyoMakernoteDirectory;
     67import com.drew.metadata.exif.makernotes.SigmaMakernoteDirectory;
     68import com.drew.metadata.exif.makernotes.SonyType1MakernoteDirectory;
     69import com.drew.metadata.exif.makernotes.SonyType6MakernoteDirectory;
    4170import com.drew.metadata.iptc.IptcReader;
    4271import com.drew.metadata.tiff.DirectoryTiffHandler;
     
    5483    public ExifTiffHandler(@NotNull Metadata metadata, @Nullable Directory parentDirectory)
    5584    {
    56         super(metadata);
    57 
    58         if (parentDirectory != null)
    59             _currentDirectory.setParent(parentDirectory);
     85        super(metadata, parentDirectory);
    6086    }
    6187
     
    6793        final int panasonicRawTiffMarker = 0x0055; // for RW2 files
    6894
    69         switch (marker)
    70         {
     95        switch (marker) {
    7196            case standardTiffMarker:
    72             case olympusRawTiffMarker:      // Todo: implement an IFD0, if there is one
    73             case olympusRawTiffMarker2:     // Todo: implement an IFD0, if there is one
     97            case olympusRawTiffMarker:      // TODO implement an IFD0, if there is one
     98            case olympusRawTiffMarker2:     // TODO implement an IFD0, if there is one
    7499                pushDirectory(ExifIFD0Directory.class);
    75100                break;
     
    172197
    173198        // an unknown (0) formatCode needs to be potentially handled later as a highly custom directory tag
    174         if(formatCode == 0)
     199        if (formatCode == 0)
    175200            return 0L;
    176201
     
    185210                                    final int byteCount) throws IOException
    186211    {
     212        assert(_currentDirectory != null);
     213
    187214        // Some 0x0000 tags have a 0 byteCount. Determine whether it's bad.
    188         if (tagId == 0)
    189         {
    190             if (_currentDirectory.containsTag(tagId))
    191             {
     215        if (tagId == 0) {
     216            if (_currentDirectory.containsTag(tagId)) {
    192217                // Let it go through for now. Some directories handle it, some don't
    193218                return false;
     
    215240        }
    216241
    217         if (HandlePrintIM(_currentDirectory, tagId))
     242        if (handlePrintIM(_currentDirectory, tagId))
    218243        {
    219244            PrintIMDirectory printIMDirectory = new PrintIMDirectory();
    220245            printIMDirectory.setParent(_currentDirectory);
    221246            _metadata.addDirectory(printIMDirectory);
    222             ProcessPrintIM(printIMDirectory, tagOffset, reader, byteCount);
     247            processPrintIM(printIMDirectory, tagOffset, reader, byteCount);
    223248            return true;
    224249        }
     
    226251        // Note: these also appear in tryEnterSubIfd because some are IFD pointers while others begin immediately
    227252        // for the same directories
    228         if(_currentDirectory instanceof OlympusMakernoteDirectory)
    229         {
    230             switch (tagId)
    231             {
     253        if (_currentDirectory instanceof OlympusMakernoteDirectory) {
     254            switch (tagId) {
    232255                case OlympusMakernoteDirectory.TAG_EQUIPMENT:
    233256                    pushDirectory(OlympusEquipmentMakernoteDirectory.class);
     
    265288        }
    266289
    267         if (_currentDirectory instanceof PanasonicRawIFD0Directory)
    268         {
     290        if (_currentDirectory instanceof PanasonicRawIFD0Directory) {
    269291            // these contain binary data with specific offsets, and can't be processed as regular ifd's.
    270292            // The binary data is broken into 'fake' tags and there is a pattern.
    271             switch (tagId)
    272             {
     293            switch (tagId) {
    273294                case PanasonicRawIFD0Directory.TagWbInfo:
    274295                    PanasonicRawWbInfoDirectory dirWbInfo = new PanasonicRawWbInfoDirectory();
    275296                    dirWbInfo.setParent(_currentDirectory);
    276297                    _metadata.addDirectory(dirWbInfo);
    277                     ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2);
     298                    processBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2);
    278299                    return true;
    279300                case PanasonicRawIFD0Directory.TagWbInfo2:
     
    281302                    dirWbInfo2.setParent(_currentDirectory);
    282303                    _metadata.addDirectory(dirWbInfo2);
    283                     ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3);
     304                    processBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3);
    284305                    return true;
    285306                case PanasonicRawIFD0Directory.TagDistortionInfo:
     
    287308                    dirDistort.setParent(_currentDirectory);
    288309                    _metadata.addDirectory(dirDistort);
    289                     ProcessBinary(dirDistort, tagOffset, reader, byteCount, true, 1);
     310                    processBinary(dirDistort, tagOffset, reader, byteCount, true, 1);
    290311                    return true;
    291312            }
     
    293314
    294315        // Panasonic RAW sometimes contains an embedded version of the data as a JPG file.
    295         if (tagId == PanasonicRawIFD0Directory.TagJpgFromRaw && _currentDirectory instanceof PanasonicRawIFD0Directory)
    296         {
     316        if (tagId == PanasonicRawIFD0Directory.TagJpgFromRaw && _currentDirectory instanceof PanasonicRawIFD0Directory) {
    297317            byte[] jpegrawbytes = reader.getBytes(tagOffset, byteCount);
    298318
     
    316336    }
    317337
    318     private static void ProcessBinary(@NotNull final Directory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount, final Boolean issigned, final int arrayLength) throws IOException
     338    private static void processBinary(@NotNull final Directory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount, final Boolean isSigned, final int arrayLength) throws IOException
    319339    {
    320340        // expects signed/unsigned int16 (for now)
    321         //int byteSize = issigned ? sizeof(short) : sizeof(ushort);
     341        //int byteSize = isSigned ? sizeof(short) : sizeof(ushort);
    322342        int byteSize = 2;
    323343
    324344        // 'directory' is assumed to contain tags that correspond to the byte position unless it's a set of bytes
    325         for (int i = 0; i < byteCount; i++)
    326         {
    327             if (directory.hasTagName(i))
    328             {
     345        for (int i = 0; i < byteCount; i++) {
     346            if (directory.hasTagName(i)) {
    329347                // only process this tag if the 'next' integral tag exists. Otherwise, it's a set of bytes
    330                 if (i < byteCount - 1 && directory.hasTagName(i + 1))
    331                 {
    332                     if(issigned)
     348                if (i < byteCount - 1 && directory.hasTagName(i + 1)) {
     349                    if (isSigned)
    333350                        directory.setObject(i, reader.getInt16(tagValueOffset + (i* byteSize)));
    334351                    else
    335352                        directory.setObject(i, reader.getUInt16(tagValueOffset + (i* byteSize)));
    336                 }
    337                 else
    338                 {
     353                } else {
    339354                    // the next arrayLength bytes are a multi-byte value
    340                     if (issigned)
    341                     {
     355                    if (isSigned) {
    342356                        short[] val = new short[arrayLength];
    343357                        for (int j = 0; j<val.length; j++)
    344358                            val[j] = reader.getInt16(tagValueOffset + ((i + j) * byteSize));
    345359                        directory.setObjectArray(i, val);
    346                     }
    347                     else
    348                     {
     360                    } else {
    349361                        int[] val = new int[arrayLength];
    350362                        for (int j = 0; j<val.length; j++)
     
    359371    }
    360372
     373    /** Read a given number of bytes from the stream
     374     *
     375     * This method is employed to "suppress" attempts to read beyond end of the
     376     * file as may happen at the beginning of processMakernote when we read
     377     * increasingly longer camera makes.
     378     *
     379     * Instead of failing altogether in this context we return an empty string
     380     * which will fail all sensible attempts to compare to makes while avoiding
     381     * a full-on failure.
     382     */
     383    @NotNull
     384    private static String getReaderString(final @NotNull RandomAccessReader reader, final int makernoteOffset, final int bytesRequested) throws IOException
     385    {
     386        try {
     387            return reader.getString(makernoteOffset, bytesRequested, Charsets.UTF_8);
     388        } catch(BufferBoundsException e) {
     389            return "";
     390        }
     391    }
     392
    361393    private boolean processMakernote(final int makernoteOffset,
    362394                                     final @NotNull Set<Integer> processedIfdOffsets,
     
    364396                                     final @NotNull RandomAccessReader reader) throws IOException
    365397    {
     398        assert(_currentDirectory != null);
     399
    366400        // Determine the camera model and makernote format.
    367401        Directory ifd0Directory = _metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
     
    369403        String cameraMake = ifd0Directory == null ? null : ifd0Directory.getString(ExifIFD0Directory.TAG_MAKE);
    370404
    371         final String firstTwoChars    = reader.getString(makernoteOffset, 2, Charsets.UTF_8);
    372         final String firstThreeChars  = reader.getString(makernoteOffset, 3, Charsets.UTF_8);
    373         final String firstFourChars   = reader.getString(makernoteOffset, 4, Charsets.UTF_8);
    374         final String firstFiveChars   = reader.getString(makernoteOffset, 5, Charsets.UTF_8);
    375         final String firstSixChars    = reader.getString(makernoteOffset, 6, Charsets.UTF_8);
    376         final String firstSevenChars  = reader.getString(makernoteOffset, 7, Charsets.UTF_8);
    377         final String firstEightChars  = reader.getString(makernoteOffset, 8, Charsets.UTF_8);
    378         final String firstNineChars   = reader.getString(makernoteOffset, 9, Charsets.UTF_8);
    379         final String firstTenChars    = reader.getString(makernoteOffset, 10, Charsets.UTF_8);
    380         final String firstTwelveChars = reader.getString(makernoteOffset, 12, Charsets.UTF_8);
     405        final String firstTwoChars    = getReaderString(reader, makernoteOffset, 2);
     406        final String firstThreeChars  = getReaderString(reader, makernoteOffset, 3);
     407        final String firstFourChars   = getReaderString(reader, makernoteOffset, 4);
     408        final String firstFiveChars   = getReaderString(reader, makernoteOffset, 5);
     409        final String firstSixChars    = getReaderString(reader, makernoteOffset, 6);
     410        final String firstSevenChars  = getReaderString(reader, makernoteOffset, 7);
     411        final String firstEightChars  = getReaderString(reader, makernoteOffset, 8);
     412        final String firstNineChars   = getReaderString(reader, makernoteOffset, 9);
     413        final String firstTenChars    = getReaderString(reader, makernoteOffset, 10);
     414        final String firstTwelveChars = getReaderString(reader, makernoteOffset, 12);
    381415
    382416        boolean byteOrderBefore = reader.isMotorolaByteOrder();
     
    501535                return false;
    502536            }
    503         } else if ("Panasonic\u0000\u0000\u0000".equals(reader.getString(makernoteOffset, 12, Charsets.UTF_8))) {
     537        } else if ("Panasonic\u0000\u0000\u0000".equals(firstTwelveChars)) {
    504538            // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD
    505539            // Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment
     
    575609    }
    576610
    577     private static Boolean HandlePrintIM(@NotNull final Directory directory, final int tagId)
     611    private static boolean handlePrintIM(@NotNull final Directory directory, final int tagId)
    578612    {
    579613        if (tagId == ExifDirectoryBase.TAG_PRINT_IMAGE_MATCHING_INFO)
    580614            return true;
    581615
    582         if (tagId == 0x0E00)
    583         {
     616        if (tagId == 0x0E00) {
    584617            // Tempting to say every tagid of 0x0E00 is a PIM tag, but can't be 100% sure
    585618            if (directory instanceof CasioType2MakernoteDirectory ||
     
    606639    /// lib\Image\ExifTool\PrintIM.pm
    607640    /// </remarks>
    608     private static void ProcessPrintIM(@NotNull final PrintIMDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount) throws IOException
     641    private static void processPrintIM(@NotNull final PrintIMDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount) throws IOException
    609642    {
    610643        Boolean resetByteOrder = null;
    611644
    612         if (byteCount == 0)
    613         {
     645        if (byteCount == 0) {
    614646            directory.addError("Empty PrintIM data");
    615647            return;
    616648        }
    617649
    618         if (byteCount <= 15)
    619         {
     650        if (byteCount <= 15) {
    620651            directory.addError("Bad PrintIM data");
    621652            return;
     
    624655        String header = reader.getString(tagValueOffset, 12, Charsets.UTF_8);
    625656
    626         if (!header.startsWith("PrintIM")) //, StringComparison.Ordinal))
    627         {
     657        if (!header.startsWith("PrintIM")) {
    628658            directory.addError("Invalid PrintIM header");
    629659            return;
     
    632662        // check size of PrintIM block
    633663        int num = reader.getUInt16(tagValueOffset + 14);
    634         if (byteCount < 16 + num * 6)
    635         {
     664
     665        if (byteCount < 16 + num * 6) {
    636666            // size is too big, maybe byte ordering is wrong
    637667            resetByteOrder = reader.isMotorolaByteOrder();
    638668            reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder());
    639669            num = reader.getUInt16(tagValueOffset + 14);
    640             if (byteCount < 16 + num * 6)
    641             {
     670            if (byteCount < 16 + num * 6) {
    642671                directory.addError("Bad PrintIM size");
    643672                return;
     
    647676        directory.setObject(PrintIMDirectory.TagPrintImVersion, header.substring(8, 12));
    648677
    649         for (int n = 0; n < num; n++)
    650         {
     678        for (int n = 0; n < num; n++) {
    651679            int pos = tagValueOffset + 16 + n * 6;
    652680            int tag = reader.getUInt16(pos);
     
    712740            build = null;
    713741        }
    714         if (build != null)
    715         {
     742
     743        if (build != null) {
    716744            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d.%s", major, minor, revision, build));
    717         }
    718         else
    719         {
     745        } else {
    720746            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d", major, minor, revision));
    721747            directory.addError("Error processing Reconyx HyperFire makernote data: build '" + buildYearAndDate + "' is not in the expected format and will be omitted from Firmware Version.");
     
    746772            (month >= 1 && month < 13) &&
    747773            (day >= 1 && day < 32) &&
    748             (year >= 1 && year <= 9999))
    749         {
     774            (year >= 1 && year <= 9999)) {
    750775            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL,
    751776                    String.format("%4d:%2d:%2d %2d:%2d:%2d", year, month, day, hour, minutes, seconds));
    752         }
    753         else
    754         {
     777        } else {
    755778            directory.addError("Error processing Reconyx HyperFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time.");
    756779        }
     
    778801        /*uint makernoteID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernoteID));
    779802        directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernoteID, makernoteID);
    780         if (makernoteID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_ID)
    781         {
     803        if (makernoteID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_ID) {
    782804            directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote ID 0x" + makernoteID.ToString("x8"));
    783805            return;
     
    786808        uint makernotePublicID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID));
    787809        directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID, makernotePublicID);
    788         if (makernotePublicID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_PUBLIC_ID)
    789         {
     810        if (makernotePublicID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_PUBLIC_ID) {
    790811            directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote Public ID 0x" + makernotePublicID.ToString("x8"));
    791812            return;
     
    818839            (month >= 1 && month < 13) &&
    819840            (day >= 1 && day < 32) &&
    820             (year >= 1 && year <= 9999))
    821         {
     841            (year >= 1 && year <= 9999)) {
    822842            directory.Set(ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL, new DateTime(year, month, day, hour, minutes, seconds, DateTimeKind.Unspecified));
    823         }
    824         else
    825         {
     843        } else {
    826844            directory.addError("Error processing Reconyx UltraFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time.");
    827845        }*/
Note: See TracChangeset for help on using the changeset viewer.