Ever needed to read in EXIF data from images or other files in R? ExifTool by Phil Harvey is the most comprenesive tool available for reading, writing and editing meta information in a wide variety of files. ExifTool supports many different metadata formats including EXIF, GPS, IPTC, XMP, JFIF, GeoTIFF, ICC Profile, Photoshop IRB, FlashPix, AFCP and ID3, as well as the maker notes of many digital cameras by Canon, Casio, FLIR, FujiFilm, GE, HP, JVC/Victor, Kodak, Leaf, Minolta/Konica-Minolta, Motorola, Nikon, Nintendo, Olympus/Epson, Panasonic/Leica, Pentax/Asahi, Phase One, Reconyx, Ricoh, Samsung, Sanyo, Sigma/Foveon and Sony. This package provides a thin wrapper around ExifTool allowing the reading of image file metadata with a single command.
You will need Perl to use exifr, which may already be installed on your system (Mac, Linux). If you are on Windows you need to install Perl before installing exifr (easily done from Strawberry Perl or Active State Perl. Mac users can also install ExifTool directly from sourceforge, which is not necessary but may be useful if ExifTool is to be used outside of R.
You can install exifr from github with:
# install.packages("devtools")
devtools::install_github("paleolimbot/exifr")
…or from CRAN with:
install.packages("exifr")
If you can load the package, everything should be installed correctly:
library(exifr)
#> Using ExifTool version 12.22
It makes the most sense to use the read_exif()
function with
list.files()
, but it will also process directories (when using
recursive = TRUE
).
image_files <- list.files(system.file("images", package = "exifr"), full.names = TRUE)
read_exif(image_files)
#> # A tibble: 2 x 275
#> SourceFile ExifToolVersion FileName Directory FileSize FileModifyDate
#> <chr> <dbl> <chr> <chr> <int> <chr>
#> 1 /Library/… 12.2 binary_… /Library… 13726 2021:03:20 10…
#> 2 /Library/… 12.2 Canon.j… /Library… 2697 2021:03:20 10…
#> # … with 269 more variables: FileAccessDate <chr>, FileInodeChangeDate <chr>,
#> # FilePermissions <int>, FileType <chr>, FileTypeExtension <chr>,
#> # MIMEType <chr>, JFIFVersion <chr>, ExifByteOrder <chr>, Make <chr>,
#> # Model <chr>, Orientation <int>, XResolution <int>, YResolution <int>,
#> # ResolutionUnit <int>, Software <chr>, ModifyDate <chr>, Artist <chr>,
#> # YCbCrPositioning <int>, ExposureTime <dbl>, FNumber <dbl>,
#> # ExposureProgram <int>, ISO <int>, SensitivityType <int>, ExifVersion <chr>,
#> # DateTimeOriginal <chr>, CreateDate <chr>, ComponentsConfiguration <chr>,
#> # CompressedBitsPerPixel <int>, ExposureCompensation <dbl>,
#> # MaxApertureValue <dbl>, MeteringMode <int>, LightSource <int>, Flash <int>,
#> # FocalLength <dbl>, Warning <chr>, ImageQuality <int>,
#> # FirmwareVersion <chr>, WhiteBalance <int>, FocusMode <int>,
#> # AFAreaMode <chr>, ImageStabilization <int>, MacroMode <int>,
#> # ShootingMode <int>, Audio <int>, DataDump <chr>, WhiteBalanceBias <int>,
#> # FlashBias <int>, InternalSerialNumber <chr>, PanasonicExifVersion <chr>,
#> # VideoFrameRate <int>, ColorEffect <int>, TimeSincePowerOn <dbl>,
#> # BurstMode <int>, SequenceNumber <int>, ContrastMode <int>,
#> # NoiseReduction <int>, SelfTimer <int>, Rotation <int>, AFAssistLamp <int>,
#> # ColorMode <int>, OpticalZoomMode <int>, ConversionLens <int>,
#> # TravelDay <int>, BatteryLevel <int>, WorldTimeLocation <int>,
#> # ProgramISO <int>, AdvancedSceneType <int>, FacesDetected <int>,
#> # AFPointPosition <chr>, NumFacePositions <int>, Face1Position <chr>,
#> # Face2Position <chr>, Face3Position <chr>, Face4Position <chr>,
#> # Face5Position <chr>, IntelligentExposure <int>, FacesRecognized <int>,
#> # RecognizedFace1Name <chr>, RecognizedFace1Position <chr>,
#> # RecognizedFace1Age <chr>, RecognizedFace2Name <chr>,
#> # RecognizedFace2Position <chr>, RecognizedFace2Age <chr>,
#> # RecognizedFace3Name <chr>, RecognizedFace3Position <chr>,
#> # RecognizedFace3Age <chr>, FlashWarning <int>, Title <chr>, BabyName <chr>,
#> # Location <chr>, IntelligentResolution <int>, HDRShot <int>,
#> # BurstSpeed <int>, ClearRetouch <int>, WBShiftCreativeControl <int>,
#> # SweepPanoramaDirection <int>, SweepPanoramaFieldOfView <int>,
#> # InternalNDFilter <dbl>, FilterEffect <chr>, ClearRetouchValue <dbl>, …
You’ll notice there are a lot of columns! You can choose the exact tags
you want to extract using the tags
argument:
read_exif(image_files, tags = c("filename", "imagesize"))
#> # A tibble: 2 x 3
#> SourceFile FileName ImageSize
#> <chr> <chr> <chr>
#> 1 /Library/Frameworks/R.framework/Versions/4.0/Resources/… binary_tag… 30 25
#> 2 /Library/Frameworks/R.framework/Versions/4.0/Resources/… Canon.jpg 8 8
In the background, read_exif()
is calling exiftool
on the console,
and reading the results to R. You can see the exact command used by
read_exif()
by passing quiet = FALSE
. This can be useful when
debugging, as occasionally images need to get read in that need some
kind of special treatment.
read_exif(image_files, tags = c("filename", "imagesize"), quiet = FALSE)
#> Generating command line arguments...
#> Running 1 commands
#> 'perl' '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/exiftool/exiftool.pl' -n -j -q -b -filename -imagesize '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/binary_tag.JPG' '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/Canon.jpg'
#> # A tibble: 2 x 3
#> SourceFile FileName ImageSize
#> <chr> <chr> <chr>
#> 1 /Library/Frameworks/R.framework/Versions/4.0/Resources/… binary_tag… 30 25
#> 2 /Library/Frameworks/R.framework/Versions/4.0/Resources/… Canon.jpg 8 8
You can also roll-your-own exiftool
call by using exiftool_call()
.
For the previous example, it would look something like this:
exiftool_call(args = c("-n", "-j", "-q", "-filename", "-imagesize"), fnames = image_files)
#> 'perl' '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/exiftool/exiftool.pl' -n -j -q -filename -imagesize '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/binary_tag.JPG' '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/Canon.jpg'
#> [{
#> "SourceFile": "/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/binary_tag.JPG",
#> "FileName": "binary_tag.JPG",
#> "ImageSize": "30 25"
#> },
#> {
#> "SourceFile": "/Library/Frameworks/R.framework/Versions/4.0/Resources/library/exifr/images/Canon.jpg",
#> "FileName": "Canon.jpg",
#> "ImageSize": "8 8"
#> }]