drewnoakes / metadata-extractor

Extracts Exif, IPTC, XMP, ICC and other metadata from image, video and audio files
Apache License 2.0
2.55k stars 479 forks source link

JPG Metadata-Tag seems to be skipped / ignored #546

Closed mfroehler closed 3 years ago

mfroehler commented 3 years ago

testbild riwa_2 2021-07-13 17_33_40-Window

The GPS Longitude of the image attached is not returned. Maybe it is because if it is the last tag or there seem to be completely empty tags in the data and a internal counter may go wrong.

Here the code i use to read the image metadata:


private String[] getCoordsFromFile(File file) {
    try {
        Metadata md = ImageMetadataReader.readMetadata(file);
        Iterable iter = md.getDirectories();
        Iterator<Directory> it = iter.iterator();

        String latitude = null;
        String longitude = null;

        while (it.hasNext()) {
            Directory dir = it.next();
            if (dir.getName().equals("GPS")) {
                boolean haslong = false;
                boolean haslat = false;
                for (int i = 0; i < dir.getTagCount(); i++) {

                    if (dir.getTagName(i).equals("GPS Latitude")) {
                        latitude = dir.getDescription(i);
                        if (haslat) {
                            break;
                        }
                        haslong = true;
                    } else if (dir.getTagName(i).equals("GPS Longitude")) {
                        longitude = dir.getDescription(i);
                        if (haslong) {
                            break;
                        }
                        haslat = true;
                    }

                }
            }
        }
        String[] result = {latitude, longitude};
        return result;
    } catch (Exception e) {
        String[] result = {null, null};
        return result;
    }
}

jefftucker1952 commented 3 years ago

Not sure what's wrong with your code, but I'm using an application (jAlbum) that, in turn, uses metadata-extractor to pull the metadata, and it's having no problem retrieving the GPS coordinates from that image.

ss009050

ss009051

jefftucker1952 commented 3 years ago

Try drew's own code:

public static void saveMetadataToFile(File image, File output)

    throws ImageProcessingException, IOException
{
    Metadata metadata = ImageMetadataReader.readMetadata(image);
    PrintStream printStream = new PrintStream(output);
    try {
        for (Directory directory : metadata.getDirectories()) {
            for (Tag tag : directory.getTags()) {
                printStream.println(tag);
            }
        }
    } finally {
        printStream.close();
    }
}
mfroehler commented 3 years ago

Hi Jeff, thanks for your response. It´s not the point there is something wrong with my code. It seems to be something wrong with the image I attached or there may be bug in the lib. If you want to test with your code, use the image I attached an try to find out the gps location using metadata-extractor. If it works it would be nice if you let me know how you achived this. Best regard Michael

P.S.: My asumption is that if the GPS Longitute Tag is the last one it seems to be ignored and is not returned by metadata-extractor.

P.P.S.: I will investigate if maybe using directory.getTagCount() is the problem.

jefftucker1952 commented 3 years ago

I did exactly that - used drew's code. Here's the output it produced.

metaout.txt

mfroehler commented 3 years ago

Hi Jeff,

againt thanks for your fast answer!

I found the solution know (with your help)

Its "dir.getTagName(index)"

index seems to be not zero based but one based.

If I call "dir.getTagName(0)" I get a "Version ID" as return value. I suppose this is not a bug. It was ment to work that way.

I will use dir.getTags() in the future an everything will work fine.

Thanks for your support.

Regards

Michael

Following Code:

public static void main(String[] args) {
    try {
        File testImg = new File("C:\\temp\\testbild riwa_2.jpg");
        Metadata md = ImageMetadataReader.readMetadata(testImg);
        Iterable iter = md.getDirectories();
        Iterator<Directory> it = iter.iterator();
        while (it.hasNext()) {
            Directory dir = it.next();
            if (dir.getName().equals("GPS")) {
                int tagCount1 = dir.getTagCount();
                Collection<Tag> tags = dir.getTags();
                //Zero based index? -> wrong - last tagname is not returned
                for(int i=0;i<tagCount1;i++){
                    System.out.println(String.format("Tagname by index - zero based : %s",dir.getTagName(i)));
                }
                //One based index? -> works but does not return version-id
                for(int i=1;i<=tagCount1;i++){
                    System.out.println(String.format("Tagname by Index one based : %s",dir.getTagName(i)));
                }
                //Works -> does not return version-id
                for(Tag tag:tags){
                    System.out.println(String.format("Tagname by tag : %s",tag.getTagName()));
                }
            }
        }
    } catch (ImageProcessingException | IOException e) {
        e.printStackTrace();
    }
}

returns the following output

Tagname by index - zero based : GPS Version ID Tagname by index - zero based : GPS Latitude Ref Tagname by index - zero based : GPS Latitude Tagname by index - zero based : GPS Longitude Ref Tagname by Index one based : GPS Latitude Ref Tagname by Index one based : GPS Latitude Tagname by Index one based : GPS Longitude Ref Tagname by Index one based : GPS Longitude Tagname by tag : GPS Latitude Ref Tagname by tag : GPS Latitude Tagname by tag : GPS Longitude Ref Tagname by tag : GPS Longitude

drewnoakes commented 3 years ago

@mfroehler you do not need to loop through all directories to match them by name. You can get the directory you want with something like:

metadata.getDirectoriesOfType(GpsDirectory.class);

Similarly you can retrieve specific properties without having to loop through all of them.

Looping will be slow. Perhaps that doesn't matter in your case though.

mfroehler commented 3 years ago

Thanks for the hint. It was indeed legacy code i had to work with. Normally i try to avoid evil for loops with index based access. :-)