FEP-ee3a: Exif metadata support

Hi everyone!

This discussion concerns a FEP that describes how platforms can add support for exchanging Exif metadata between each other. This metadata can be extracted from image and audio files and is typically added automatically by the devices that create those files (for example digital cameras).

Photographers very often share Exif data today, usually by including it manually in the status content (often as an emoji followed by a value). However, this process is entirely manual. Client applications, on the other hand, are able to read this metadata automatically and after explicit user confirmation (which is a critical step) store it in their databases and exchange it with other platforms.

For photography-oriented platforms, this enables additional functionality, such as filtering photos taken with a specific camera body, a particular lens, and similar criteria.

PR: #750 - FEP-ee3a: Exif metadata support - fediverse/fep - Codeberg.org

4 Likes

Nice work, Pixelfed is interested in supporting this as we’re now going to display EXIF data (opt-in) and want to federate it.

Link to the FEP text: FEP-ee3a: Exif metadata support

1 Like

I also like the idea! I did a first draft for the WordPress plugin: Add EXIF metadata support for image attachments by pfefferle · Pull Request #2751 · Automattic/wordpress-activitypub · GitHub

I’m also wondering whether the FEP should explicitly state that platforms must strip all EXIF metadata from files before storing them and distributing them to other instances. It seems like everyone knows this and already does it, but it may be worth documenting explicitly.

1 Like

it looks like https://w3id.org/fep/ee3a uses http://schema.org/PropertyValue but there is already a long-existing vocabulary for EXIF data in http://www.w3.org/2003/12/exif/

using it with jsonld instead of rdf/xml, it might look like this:

{
  "@id": "_:b9",
  "@type": "http://www.w3.org/2003/12/exif/ns/IFD",
  "http://www.w3.org/2003/12/exif/ns/dateTime": "2003-01-18T16:07:30",
  "http://www.w3.org/2003/12/exif/ns/exif_IFD_Pointer": {
    "@id": "_:b10",
    "@type": "http://www.w3.org/2003/12/exif/ns/IFD",
    "http://www.w3.org/2003/12/exif/ns/apertureValue": "116/32",
    "http://www.w3.org/2003/12/exif/ns/colorSpace": "sRGB",
    "http://www.w3.org/2003/12/exif/ns/componentsConfiguration": "01 02 03 00",
    "http://www.w3.org/2003/12/exif/ns/compressedBitsPerPixel": "5/1",
    "http://www.w3.org/2003/12/exif/ns/dateTimeDigitized": "2003-01-18T16:07:30",
    "http://www.w3.org/2003/12/exif/ns/dateTimeOriginal": "2003-01-18T16:07:30",
    "http://www.w3.org/2003/12/exif/ns/exifVersion": "2.20",
    "http://www.w3.org/2003/12/exif/ns/exposureBiasValue": "96",
    "http://www.w3.org/2003/12/exif/ns/exposureTime": "1/400",
    "http://www.w3.org/2003/12/exif/ns/fNumber": "35/10",
    "http://www.w3.org/2003/12/exif/ns/flash": "Flash fired, compulsory flash mode, red-eye reduction mode",
    "http://www.w3.org/2003/12/exif/ns/flashpixVersion": "1.00",
    "http://www.w3.org/2003/12/exif/ns/focalLength": "294/32",
    "http://www.w3.org/2003/12/exif/ns/maxApertureValue": "116/32",
    "http://www.w3.org/2003/12/exif/ns/meteringMode": "Pattern",
    "http://www.w3.org/2003/12/exif/ns/shutterSpeedValue": "76"
  },
  "http://www.w3.org/2003/12/exif/ns/make": "Canon",
  "http://www.w3.org/2003/12/exif/ns/model": "Canon IXY DIGITAL 30",
  "http://www.w3.org/2003/12/exif/ns/orientation": "top-left",
  "http://www.w3.org/2003/12/exif/ns/resolutionUnit": "inch",
  "http://www.w3.org/2003/12/exif/ns/xResolution": "180/1",
  "http://www.w3.org/2003/12/exif/ns/yCbCrPositioning": "centered",
  "http://www.w3.org/2003/12/exif/ns/yResolution": "180/1"
}

compacted with a prefix, it might look like this:

{
  "@context": {
    "exif": "http://www.w3.org/2003/12/exif/ns/"
  },
  "@id": "_:b9",
  "@type": "exif:IFD",
  "exif:dateTime": "2003-01-18T16:07:30",
  "exif:exif_IFD_Pointer": {
    "@id": "_:b10",
    "@type": "exif:IFD",
    "exif:apertureValue": "116/32",
    "exif:colorSpace": "sRGB",
    "exif:componentsConfiguration": "01 02 03 00",
    "exif:compressedBitsPerPixel": "5/1",
    "exif:dateTimeDigitized": "2003-01-18T16:07:30",
    "exif:dateTimeOriginal": "2003-01-18T16:07:30",
    "exif:exifVersion": "2.20",
    "exif:exposureBiasValue": "96",
    "exif:exposureTime": "1/400",
    "exif:fNumber": "35/10",
    "exif:flash": "Flash fired, compulsory flash mode, red-eye reduction mode",
    "exif:flashpixVersion": "1.00",
    "exif:focalLength": "294/32",
    "exif:maxApertureValue": "116/32",
    "exif:meteringMode": "Pattern",
    "exif:shutterSpeedValue": "76"
  },
  "exif:make": "Canon",
  "exif:model": "Canon IXY DIGITAL 30",
  "exif:orientation": "top-left",
  "exif:resolutionUnit": "inch",
  "exif:xResolution": "180/1",
  "exif:yCbCrPositioning": "centered",
  "exif:yResolution": "180/1"
}

you could proceed to come up with some context using term definitions and your desired mapping to “plain JSON” output. at minimum, you compact the following graph:

{
  "http://www.w3.org/2003/12/exif/ns/exifdata": {
    "@type": "http://www.w3.org/2003/12/exif/ns/IFD",
  "http://www.w3.org/2003/12/exif/ns/make": "Canon",
  "http://www.w3.org/2003/12/exif/ns/model": "Canon IXY DIGITAL 30",
  "http://www.w3.org/2003/12/exif/ns/dateTime": "2003-01-18T16:07:30",
  "http://www.w3.org/2003/12/exif/ns/exif_IFD_Pointer": {
    "http://www.w3.org/2003/12/exif/ns/apertureValue": "116/32",
    "http://www.w3.org/2003/12/exif/ns/colorSpace": "sRGB",
    "http://www.w3.org/2003/12/exif/ns/exposureTime": "1/400",
    "http://www.w3.org/2003/12/exif/ns/fNumber": "35/10",
    "http://www.w3.org/2003/12/exif/ns/flash": "Flash fired, compulsory flash mode, red-eye reduction mode",
    "http://www.w3.org/2003/12/exif/ns/focalLength": "294/32"
  }
  }
}

against the following context:

{
  "exif": "http://www.w3.org/2003/12/exif/ns/",
  "exifdata": {
    "@id": "exif:exifdata",
    "@context": {
      "@vocab": "http://www.w3.org/2003/12/exif/ns/"
    }
  }
}

and get the following “plain JSON” serialization:

{
  "@context": {
    "exif": "http://www.w3.org/2003/12/exif/ns/",
    "exifdata": {
      "@id": "exif:exifdata",
      "@context": {
        "@vocab": "http://www.w3.org/2003/12/exif/ns/"
      }
    }
  },
  "exifdata": {
    "@type": "IFD",
    "dateTime": "2003-01-18T16:07:30",
    "exif_IFD_Pointer": {
      "apertureValue": "116/32",
      "colorSpace": "sRGB",
      "exposureTime": "1/400",
      "fNumber": "35/10",
      "flash": "Flash fired, compulsory flash mode, red-eye reduction mode",
      "focalLength": "294/32"
    },
    "make": "Canon",
    "model": "Canon IXY DIGITAL 30"
  }
}

i’m not 100% sure if that’s “correct” since i haven’t looked at the namespace for that long, but i wanted to point you to existing prior work at least.

1 Like

This FEP utilizes the “exifData” property, which can be applied to “ImageObject.” This is detailed in the following resource: ImageObject - Schema.org Type. In my opinion, this approach is significantly more straightforward than the w3.org solution.

the downside of exifData - Schema.org Property being an array of PropertyValue - Schema.org Type is that you can’t easily index into that array – you have to loop over the whole array and find the name - Schema.org Property that matches what you’re looking for. it’s generally more straightforward to use direct properties instead of indirect object forms of properties and values.

We completely agree on this. I also strongly prefer using JSON directly (so that the name immediately indicates what the value is, just as you describe). That’s why Vernissage currently uses its own extension ( Vernissage extensions to ActivityPub ).

That said, I’d like to see an FEP created for this, so that all platforms that want to transmit this information can do so in a consistent way. Everyone benefits from that - especially users, who ultimately don’t care how we pass this data around internally.

Since I described the Vernissage extension, other ideas for how to transmit this have started to appear. For me, the approach used in the extension is the best one, but then the discussion shifted to “exifData” from schema.org. And when I described it as an FEP, “exif” from w3.org came up. After that, something else might appear, and then yet another option. But in the end, that doesn’t really matter that much - the important thing for the FEP is to agree on one consistent approach. :wink: