EXIF (Exchangeable Image File Format) is a standard format maintained by the Japan Electronic and Information
Technology Industries Association (JEITA) for metadata in digital images. EXIF is used
to tag image files with metadata like image width and height, bits per pixel, camera settings
like shutter speed and a whole host of other image specific data like the GPS location where the image
was taken, and the date and time when the image was taken. EXIF is supported
by almost all modern digital cameras. It is also used to tag other types of files, i.e. sound
files, PDFs, OpenOffice/LibreOffice or Word docs.
EXIF data and privacy
EXIF data in images can be a privacy concern. I.e., GPS data and the time when the picture was taken,
can reveal the place where a person was at a particular time.
A prominent example is John MacAffee, who got caught on his escape
because a Vice reporter didn't remove the EXIF data from a picture
showing him together with John McAffee during his escape, thus
revealing McAffee’s exact location.
In 2022, I walked three donkeys from northern germany to southern germany together with the
owner of the donkeys. We came by
remote places where the people were very welcoming and offered us shelter and also often food
or even an opportunity to take a shower.
But they were concerned that the place gets swamped with hikers and tourists if we put the
pictures on a blog without stripping the geolocation from the images beforehand.
That’s how I came to research on EXIF data, which quickly led me to ExifTool.
ExifTool
ExifTool is a platform independent perl library accompanied by a shell program that allows modification
of EXIF tags in all sorts of files.
It’s mostly applied to images files like JPG and TIFF, but can also be applied to other types
of files.
installing ExifTool
The Debian package for ExifTool is libimage-exiftool-perl.
By default, exiftool does not list metadata with tag names, but tag descriptions:
rudolf@idoru:~/src/exiftest$ exiftool test.jpg
...
Digital Zoom Ratio : 1
Scene Capture Type : Standard
Subject Distance Range : Unknown
GPS Version ID : 2.2.0.0
GPS Latitude Ref : North
GPS Longitude Ref : East
...
To list metadata with tag names, use the parameter :
rudolf@idoru:~/src/exiftest$ exiftool -s test.jpg
...
DigitalZoomRatio : 1
SceneCaptureType : Standard
SubjectDistanceRange : Unknown
GPSVersionID : 2.2.0.0
GPSLatitudeRef : North
GPSLongitudeRef : East
GPSAltitudeRef : Above Sea Level
...
By default, exiftool only lists metadata in “known tags”. Unknown vendor specific tags
are omitted. Vendor specific tags –both known and unknown– can as well as standard tags contain sensitive data
such as GPS location, time and date, device brand and model, etc.
Unknown tags are listed with the parameters
– (lower case u) lists non-binary unknown tags.
– (upper case U) additionally lists binary unknown tags.
I’m almost always using the Parameter
to make sure that I get listed all metadata in the file.
You can list all EXIF data with .
tag families and tag groups
The docs on the ExifTool website state that “ExifTool classifies tags into groups in various families.
Here is a list of the group names in each family”.
The command issued above can be run with an additional parameter
to list the tags with their families/groups. In the example below, all tags that have a date/time
value are listed, together with their families and groups:
In the line , EXIF is the group in
family 0 (Information Type), GPS is the group in family 1 (Specific Location) and Time
is the group in family 2 (Category).
I found it easier to wrap my head around the tag classification using the path analogy:
In the line , the tag GPSdateStamp is
in path exif:gps:time for Information Type:Specific Location:Category.
composite tags
Tags in group Composite are no tags that are stored in EXIF data, but are a compositions
of other tags. I.e. the tag Composite:Time:GPSDateTime is a composition of
EXIF:GPS:GPSTimeStamp and EXIF:GPS:GPSDateStamp:
In the commandline, tag names and their familiy/group (or path) are case insensitive.
EXIF:GPS:Location:GPSVersionID and exif:gps:location:gpsversionid denote the same tag.
tags in group file
Tags in the group file are no metadata that is embedded in the EXIF data of the file.
Group File:System:Image contains tags for the file name, directory, file size and file permissions.
The values of these tags is taken directly from the underlying OS.
Group File:Image contains tags for image resolution, bits per sample, color model and
a few other related properties of the image.
By the nature of these tags, tags in these two groups can only be read but cannot be modified or
deleted.
listing tag names
lists all tag names. With ,
it lists all writable tags, with all readable tags.
The listing can be confined to a group of tag names, i.e.
lists all tag names in group exif:gps.
File:System:Time – contains file modification, access and inode change date and time.
File:Image – contains image type, mime encoding, image encoding process and colormodel.
Composite:Image – contains image with and height and number of megapixels.
With regard to privacy, only the second group File:System:Time is relevant. The file
modification time does reveal when the picture was modified.
The option
should only be used with caution on raw image types. Raw image formats sometimes
store parameters for rendering and/or image conversion as EXIF data.
modifying tags
setting the value of a tag
To set the value of the comment tag (path File:Image:Comment):
setting the value of a tag to an empty string
An alternative to delete a tag is to set the tag value to an empty string.
To write an empty string to a tag, precede the equals sign after the tag with
‘^’ (caret symbol), i.e.
.
problems with unknown tags
From my experience, both testing exiftool and using exiftool in real-world scenarios,
exiftool sometimes has a problem with modifying and deleting vendor specific tags,
aka unknown tags.
here are some examples:
Tag MakerNotes:Sony:Time:SonyDateTime:
the tag could not be deleted. Instead I get the error message “Warning: Can’t delete
Permanent tag Sony:SonyDateTime Nothing to do." What the heck is a permanent
tag?
the tag could not be set an empty string.
however, I did succeed in setting the date/time value to “January 1st, 1900 at 00:00:00”
Tag group MakerNotes:Sony
I tried to delete the group, which didn’t work but falsely reported that the operation
suceeded.
From exiftool output, deleting the group seems to work, but a quick check reveals that
the group and its tags are still there. The example above also indicates that exiftool
return codes should be treated with care.
Getting more specific and trying to delete the tag group MakerNotes:Sony:camera, I get
the message that the operation didn’t succeed.
export the EXIF data to JSON, i.e. .
Use the option if you want the thumbnail to be included in the JSON export.
clear all EXIF data in the file with .
re-import the EXIF data from the JSON EXIF data export made in the first step:
.
All tags that exiftool cannot handle properly should be gone by now.
Afterwards, check the EXIF data in the file with .
excluding tags and tag groups from operations
To exclude a tag or a tag group from an operation, precede the tag or tag group with a
double dash, i.e. to delete all GPS tags but the GPS location tags:
– set output file or output directory. If
is used, backup files are needless and not created by exiftool.
– recurse into subdirectories. If directories with a directory name beginning
with a dot (known in Unix as hidden files or hidden directories) have to be included,
use
If a directory tree is processed with exiftool and a target directory is specified with
, exiftool dumps all files it creates from processing the
input files into the target directory without creating the subdirectories as they exist in
the input directory.
To process directory trees, I found it most convenient to copy the whole dierctory tree
and process the copy of the directory tree with exiftool.
preserving file date and time
With , the original file date and time is preserved.
setting the backup mode
By default, before write operations on the original input file, exiftool creates a backup file named
from the original file.
There two modes available for writing to the original file without creating a backup:
-overwrite_original – overwrites the original file when writing information to a file.
This option should be used with caution. Backups of the original files should be
available.
-overwrite_original_in_place – this is like -overwrite_original, with an extra step
that causes the original file creation date, type, creator, label color, icon, Finder tags
and hard links to the file to be preserved. This extra step decreases the performance of
exiftool.
JSON export and import
exiftool can export EXIF data to CSV and JSON and import EXIF data from CSV and JSON as well.
I’m only interested in exporting/importing to and from JSON and omit the CSV stuff here.
To list EXIF data in JSON format, you run .
To export the EXIF data to a JSON file, you redirect the output to a file, i.e.
.
The JSON dump only includes the last part of the tag path:
rudolf@idoru:~/src/exiftest$ exiftool -j test.jpg
"SourceFile": "test.jpg",
...
"ThumbnailImage": "(Binary data 7328 bytes, use -b option to extract)",
"FocalLength35efl": "4.6 mm",
"LightValue": 9.3
rudolf@idoru:~/src/exiftest$
This poses no problem when importing such an export back into the image’s EXIF data.
On import, the tags are stored into their original path.
To include the thumbnail (which is binary data) into the JSON export, use the parameter
: .
When exporting EXIF data, the following does not work:
exclusion of tags groups, i.e. with .
exporting of binary data in unknwon tags.
putting it all together in a real life scenario
In the following scenario, I want to delete all location and time metadata from an image file
EXIF data.
I also want to clear all vendor specific tags from the EXIF data. Some vendor specific
tags contain binary data of unknown type, which can pose a privacy threat.
The non-binary vendor specific data tags are of no use to me.
I want to keep all other tags, i.e. camera settings like shutter speed, focal length and so on.
And I don’t care if someone gets it that the image was taken by a sony cell phone.
I have a backup of the image in case I screw up in any step of the procedure.
step 1: remove unknown tags
First, I export the EXIF data in JSON format. With I also export the
binary data of the standard EXIF tags to keep the image thumbnail.
The JSON export doesn’t contain any unknown vendor specific tags,
which exiftool doesn’t always handle properly.
I remove all EXIF tags and re-import the JSON export I created before:
By now, the EXIF data in the image is stripped of any unknown non-binary and binary vendor
specific tags. exiftool should be able to handle the remaining tags.
step 2: remove GPS data
I proceed with clearing all GPS data from the image EXIF data:
step 4: check for and remove any remaining date/time data
Date and time data is often contained several independent tags. This time there’s still
an XMP:XMP-exif:Time:GPSDateTime tag around, containing the date and time when the image
was shot. I also delete this tag.