dsoprea / go-exif

A very complete, highly tested, standards-driven (but customizable) EXIF reader/writer lovingly written in Go.
MIT License
510 stars 70 forks source link

ErrUnparseableValue error when reading in a JPEG file taken with a Sony digital camera #80

Open matti777 opened 1 year ago

matti777 commented 1 year ago

Im getting an ErrUnparseableValue error when reading the EXIF of a JPEG image taken with a Sony digital camera. Is that expected, what is the workaround? I would rather not toss away the existing EXIF, instead just be able to skip any unrecognized tags.

Image included as attachment; I am using the below code to read it:

    goexif "github.com/dsoprea/go-exif/v3"
    goexifundefined "github.com/dsoprea/go-exif/v3/undefined"
    jpeg "github.com/dsoprea/go-jpeg-image-structure/v2"
    "github.com/pkg/errors"

    parser := jpeg.NewJpegMediaParser()
    mediaCtx, err := parser.ParseFile(filepath)
    if err != nil {
        return 0, errors.Errorf("failed to parse JPEG file: %v", err)
    }

    sl := mediaCtx.(*jpeg.SegmentList)

    rootIb, err := sl.ConstructExifBuilder()
    if err != nil {
        if errors.Is(err, goexifundefined.ErrUnparseableValue) {
            // TODO create EXIF from scratch?
            log.Printf("No EXIF data, creating it from scratch: rootIb: %v, err: %v", rootIb, err)
        } else {
            return 0, errors.Wrap(err, "Failed to construct EXIF builder")
        }
    }

DSC00098

georgethebeatle commented 1 year ago

Hi @matti777 I believe I have hit the same issue with all images produced by my Sony NEX 3N camera. With some debugging I was able to identify that it was the PrintImageMatching tag that is causing the error you are getting.

The error is coming from here and is due to the fact that there is no registered decoder for this tag so one cannot be looked up here

A trivial solution is to simply skip tags with this name in the loop in the ifd builder's AddTagsFromExisting method. You can go mod vendor and edit that file directly adding

if ite.TagName() == "PrintImageMatching" {
    fmt.Println("Skipping tag ", ite.TagName())
    continue
}

to that loop. This did the trick for me, but is just a hack rather than a real solution.

As for the real solution there are two options that I can think of:

My intuition is that the latter is preferable.

I would also prefer if the library's errors were more detailed so that you know what is the name of the problematic tag from the error message. However, this is probably worth opening a separate issue for.

I hope all of this helps!

georgethebeatle commented 1 year ago

I just opened a PR where I try to fix this issue.

dsoprea commented 1 year ago

Actually, a third solution (also a hack) would be to add support for removing a given tag from the tags-index. When the enumerator tries to parse a tag whose ID is unknown, it'll just skip. Just copy-and-paste the Add() method as Remove() and replace its logic with remove semantics.

dsoprea commented 1 year ago

@georgethebeatle Posted comments to the PR.