joshobrien / exiftoolr Goto Github PK
View Code? Open in Web Editor NEWExifTool Functionality from R
Home Page: https://joshobrien.github.io/exiftoolr/
ExifTool Functionality from R
Home Page: https://joshobrien.github.io/exiftoolr/
Hello,
I am using your package as a dependency in my own R package to extract image metadata, and I am trying to develop functionality to write metadata to image files as well. I have developed a custom config file using the exiftool config template and troubleshooted my custom tags with help from the exiftool forum
However, whenever I try to use exif_call
to write new tags, I receive the following error: "Warning: Tag 'config' is not defined"
All tags created in my config file are subsequently undefined. I have tried saving the config file with a .config extension and a .cfg extension with the same result. I have been able to successfully use this approach with the exiftool installation from your package on the command line, and can see the new tags when I call the image in the exif_read
function. This makes me think the issue has something to do with the exif_call
function not recognizing the -config
tag.
Please let me know if I can provide any further detail to address this issue. Thank you for any assistance!
writeLines()
in construct_argfile()
isn't robust in this edge caselibrary("pdftools")
library("xmpdf")
f1 <- tempfile(fileext=".pdf")
pdf(f1)
grid::grid.text("")
invisible(dev.off())
subject <- "R\u5f88\u68d2\uff01"
d <- docinfo(subject = subject)
f_ex <- tempfile(fileext=".pdf")
set_docinfo_exiftool(d, f1, f_ex)
cat("\nWriting with exiftool works in UTF-8 locale: ", get_docinfo_pdftools(f_ex)[[1]]$subject == subject, "\n\n")
Sys.setlocale("LC_ALL", "C")
set_docinfo_exiftool(d, f1, f_ex)
cat("\nWriting with exiftool works in C locale: ", get_docinfo_pdftools(f_ex)[[1]]$subject == subject, "\n\n")
Hi @JoshOBrien - first I wanted to thank you for maintaining this helpful wrapper for ExifTool, and I think I may be experiencing an issue similar to one that was closed in late 2021. The short summary is that I have installed version 0.2.1 from GitHub, but when I install exiftool, it appears that exiftoolr cannot then find it. Here are a few more details of my system and what I have done:
version
platform x86_64-apple-darwin17.0
arch x86_64
os darwin17.0
system x86_64, darwin17.0
status
major 4
minor 2.2
year 2022
month 10
day 31
svn rev 83211
language R
version.string R version 4.2.2 (2022-10-31)
nickname Innocent and Trusting
I used devtools::install_github("JoshOBrien/exiftoolr")
to get version 0.2.1 of the package.
I then installed the exiftool software:
exiftoolr::install_exiftool()
Attempting to download ExifTool from https://exiftool.org/Image-ExifTool-12.56.tar.gz [100%] Downloaded 5187642 bytes...
Installing ExifTool in /Users/UserName/Library/Application Support/org.R-project.R/R/exiftoolr
When I check the exiftool version, the just-downloaded exiftool cannot be found:
exiftoolr::exif_version(quiet = FALSE)
Trying perl command: 'perl' --version
Perl found at: 'perl'
Trying exiftool command: '' -ver
Trying exiftool command: 'exiftool' -ver
Trying exiftool command: 'perl' '/Users/UserName/Library/Application Support/org.R-project.R/R/exiftoolr/exiftool' -ver
Error in configure_exiftoolr(quiet = quiet) :
No functioning version of Exiftool has been found. To download and install a local version into the exiftoolr package, try doing install_exiftool().
I can manually configure exiftoolr to find the installation, but this must be done every time I start RStudio:
exifPath <- '/Users/UserName/Library/Application Support/org.R-project.R/R/exiftoolr/exiftool'
exiftoolr::configure_exiftoolr( command = exifPath )
Trying perl command: 'perl' --version
Perl found at: 'perl'
Trying exiftool command: '/Users/UserName/Library/Application Support/org.R-project.R/R/exiftoolr/exiftool' -ver
ExifTool found at: '/Users/UserName/Library/Application Support/org.R-project.R/R/exiftoolr/exiftool'
exiftoolr::exif_version() [1] "12.56"
Looking back to the closed issue from 2021, there seemed to be a problem with having spaces in the path. In this example, macOS introduces a space in the Application Support
folder that exiftoolr defaults to for installation. Could this be problematic?
Thanks for your help, and I appreciate the work you've put into this package!
f <- tempfile(fileext = ".pdf")
pdf(f)
grid::grid.text('')
invisible(dev.off())
args <- "-XMP-dc:description=A description\nwith a newline"
exiftoolr::exif_call(args = args, path = f)
Trying perl command: '' --version
Trying perl command: 'perl' --version
Perl found at: 'perl'
Trying exiftool command: '' -ver
Trying exiftool command: 'exiftool' -ver
ExifTool found at: 'exiftool'
Using ExifTool version 12.40
Error: File not found - with a newline
Warning in system2(exiftoolpath, args = args, stdout = stdout) :
running command ''exiftool' -@ '/tmp/RtmpdZvxKr/args.cmd3bb64c3f3acdbb'' had status 1
[1] " 1 image files updated"
[2] " 1 files weren't updated due to errors"
attr(,"status")
[1] 1
I encountered this when running exif_read()
recursively with a file extension filter that happened to exclude all possible files, but I think more generally this is about the system2()
call to ExifTool returning character(0)
, which triggers a jsonlite::fromJSON()
error.
ExifTool itself doesn't consider this situation to be an error (on the command line, it would report that it read 0 files but otherwise exit with status 0
).
library(exiftoolr)
exif_read(
path = system.file(package = "exiftoolr", "images"),
recursive = TRUE,
tags = "filename",
args = c("--ext", "jpg")
)
#> Error: parse error: premature EOF
#>
#> (right here) ------^
Created on 2023-11-10 with reprex v2.0.2
sessionInfo()
#> R version 4.3.2 (2023-10-31)
#> Platform: aarch64-apple-darwin20 (64-bit)
#> Running under: macOS Monterey 12.6.6
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/Los_Angeles
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] exiftoolr_0.2.3
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.6.4 zip_2.3.0 cli_3.6.1 knitr_1.45
#> [5] rlang_1.1.2 xfun_0.41 purrr_1.0.2 styler_1.10.2
#> [9] jsonlite_1.8.7 data.table_1.14.8 glue_1.6.2 backports_1.4.1
#> [13] htmltools_0.5.7 rmarkdown_2.25 R.cache_0.16.0 evaluate_0.23
#> [17] fastmap_1.1.1 yaml_2.3.7 lifecycle_1.0.4 compiler_4.3.2
#> [21] fs_1.6.3 rstudioapi_0.15.0 R.oo_1.25.0 R.utils_2.12.2
#> [25] digest_0.6.33 reprex_2.0.2 curl_5.1.0 magrittr_2.0.3
#> [29] R.methodsS3_1.8.2 tools_4.3.2 withr_2.5.2
I really appreciate the time you've put into this super useful package! I'd be happy to contribute a PR to help out with a fix for this issue, if you have thoughts about how you'd want to handle it: warning (with a more informative message), return an empty something, or some other alternative?
As a side note, ExifTool does consider it an error if you've passed one or more file paths non-recursively and the extension filter excluded all of them. exif_read()
is also erroring in that scenario, but only because fromJSON()
still fails. system2
reports a warning, but not an error (and I suspect the warning may be a bit inscrutable for users who don't know how exif_call()
works internally).
library(exiftoolr)
exif_read(
path = system.file(package = "exiftoolr", "images", "Lizard.jpg"),
tags = "filename",
args = c("--ext", "jpg")
)
#> Warning in system2(exiftoolpath, args = args, stdout = stdout): running command
#> ''exiftool' -@
#> '/var/folders/2y/jjlk1tgx0tngz12f48g3znlr0000gr/T//RtmpHKhseC/args.cmd96cf7b64506e''
#> had status 1
#> Error: parse error: premature EOF
#>
#> (right here) ------^
exif_read(
path = c(system.file(package = "exiftoolr", "images", "LaSals.jpg"),
system.file(package = "exiftoolr", "images", "Lizard.jpg")),
tags = "filename",
args = c("--ext", "jpg")
)
#> Warning in system2(exiftoolpath, args = args, stdout = stdout): running command
#> ''exiftool' -@
#> '/var/folders/2y/jjlk1tgx0tngz12f48g3znlr0000gr/T//RtmpHKhseC/args.cmd96cf76dca50b''
#> had status 1
#> Error: parse error: premature EOF
#>
#> (right here) ------^
Hi Josh,
First, I would like to thank you for this very handy package!
Second, i'd like to report an issue I have to make it work on a new computer :)
I'm working on windows 10 and here are my version info :
When installing exiftoolr
either from CRAN
or github
via install.packages("exiftoolr")
or devtools::install_github("JoshOBrien/exiftoolr")
seems to work perfectly well as it creates package folder in my `R library.
Running :
system.file("exiftool", package = "exiftoolr")
returns :
"C:/Users/UsersName/Documents/R/win-library/4.1/exiftoolr/exiftool"
As it should.
I then run install_exiftool()
which do create the win_exe
folder with exiftool(-k)
in it.
install_exiftool()
returns ->
Attempting to download ExifTool from https://exiftool.org/exiftool-12.34.zip
[100%] Downloaded 6708072 bytes...
Installing ExifTool in C:/Users/UsersName/Documents/R/win-library/4.1/exiftoolr/exiftool/win_exe
system.file("exiftool/win_exe", package = "exiftoolr")
returns ->
"C:/Users/UsersName/Documents/R/win-library/4.1/exiftoolr/exiftool/win_exe"
and
system.file("exiftool/win_exe/exiftool(-k).exe", package = "exiftoolr")
returns ->
"C:/Users/UsersName/Documents/R/win-library/4.1/exiftoolr/exiftool/win_exe/exiftool(-k).exe"
So far all seems good to me.
But when I run configure_exiftoolr()
it returns :
Trying perl command: "" --version
Trying perl command: "perl" --version
Trying perl command: "C:\Perl64\bin\perl" --version
Trying perl command: "C:\Perl\bin\perl" --version
Trying perl command: "C:\Strawberry\perl\bin\perl" --version
Trying exiftool command: -ver
Trying exiftool command: C:/Users/UsersName/Documents/R/win-library/4.1/exiftoolr/exiftool/win_exe/exiftool(-k).exe -ver
Trying exiftool command: exiftool -ver
Error in configure_exiftoolr() :
No functioning version of Exiftool has been found. To
download and install a local version into the exiftoolr
package, try doing install_exiftool()
I have probably done something wrong but can't figure out what...
Would you have any idea/tips/ or suggestion?
Have a great day and thank you!
Hi Josh
thanks for the useful package.
While using exif_read(), I have stumbled upon the following problem:
I need to call it with the charset argument. However, charset can be used on different levels; in my case I need it once for the filename and once for the tags themselves. So my call (on CLI) goes like this:
exiftool "c:/temp/myfile.jpg" -charset exiftool=cp850 -charset filename=cp1250
However, trying to replicate this with exif_read() does not work.
exif_read(path = myimage, args = c("-charset", "exiftool=cp850", "-charset", "filename=cp1250"))
I get an error:
Error: lexical error: invalid char in json text.
Error: File not found - filenam
The way I understand it is that the function first makes a list of unique arguments, therefore throwing away one of the charset argument. Then obviously it tries to call exiftool with the argument "filename" which does not exist. Hence I wonder if the unique() call is really necessary or at least if you could make it optional.
Thanks, Daniel
Hi Josh,
Firstly thank you for creating this wrapper. We have been keen to add GPS tags to site and drop camera photos for ages and to potentially do it all from R would be brilliant.
I just can't seem to get the exif_call() function to handle this use case, no doubt a syntax issue on my part, and was wondering if you could assist.
I'm using a Windows OS so followed your install instructions and can reproduce your example.
On doing some digging I came across some insight from Phil Harvey which appears to suit my case here.
I attempted to recreate his example by:
exif_call(path = "./photos/BHuntley-14-09-19-8310.jpg", args = c("-csv=./photos/position_data.txt", "-gpslatituderef=N", "-gpslongituderef=W"))
The position_data.txt is set up similar to the example but only contains SourceFile, GPSLatitude, and GPSLongitude headers with data for the image specified.
When I run it it gives me the diagnostic "1 image files updated" but when I call exif_read(./photos/BHuntley-14-09-19-8310.jpg, tags = "GPS")
it returns no gps related attributes and only the SourceFile name.
I'm doing all of the above within an RStudio project (hence the filepaths).
Any ideas?
Thanks
Bart
Hi Josh,
I'm teaching an R workshop next week and some of my code uses exiftoolr
to teach folks how to extract and view photo metadata. Thanks for making this great package!
While my computer can "see" Exiftool, many of the participants are struggling to point exiftoolr
to Exiftool. They keep getting errors.
Of note:
C:/Users/UserName/OneDrive - Government/Documents/R/win-library/3.6/exiftoolr/exiftool
, I found that Exiftool was there, but it was named "exiftool(-k)". I deleted the (-k) part and tried again - no dice.Here's what we tried:
library(exiftoolr)
# Install from the web
install_exiftool()
Attempting to download ExifTool from https://sno.phy.queensu.ca/~phil/exiftool/exiftool-11.55.zip
Error in curl_download(install_url, tmpfile, quiet = quiet) :
Timeout was reached: Connection timed out after 10000 milliseconds
# That didn't work - install from local zip file downloaded from internet
install_exiftool(local_exiftool = "C:\\Users\\UserName\\Downloads\\exiftool-11.55.zip")
Installing ExifTool in C:/Users/UserName/OneDrive - Government/Documents/R/win-library/3.6/exiftoolr/exiftool
exif_read("test.JPG")
Error in configure_exiftoolr(quiet = quiet) :
No functioning version of Exiftool has been found. To
download and install a local version into the exiftoolr
package, try doing install_exiftool().
.libPaths()
[1] "C:/Users/UserName/OneDrive - Government/Documents/R/win-library/3.6"
[2] "C:/Program Files/R/R-3.6.1/library
Any suggestions you have are much appreciated!
tools::R_user_dir("exiftoolr")
should generally be more writable by users than system.file(package = "exiftoolr")
.
exiftoolr
is installed by an admin in the shared library of a multi-user server (and hence is owned by "root"). I already have a system install of exiftool
so this isn't a problem but my attempt of using install_exiftool()
to see what happens failed for this reason.Not sure if it would be better to use R_user_dir("exiftoolr", "data")
(default) versus R_user_dir("exiftoolr", "config")
versus R_user_dir("exiftoolr", "cache")
but it probably doesn't matter too much which one is chosen.
R_user_dir()
was introduced in R 4.0.0 so you'd need to bump your R version requirement or use the {backports}
version
Hello Josh,
I've been using your package for a while now and when I updated my version of R to 4.2, I started getting the following error whenever I run exif_call() and exif_read():
exif_read()
Error in if (com == paste(shQuote(perl_path), shQuote(NULL))) { :
argument is of length zero
I've tried running both with the path specified and it doesn't work either
exif_call(path = "C:/Users/rcyam/AppData/Local/R/win-library/4.2/exiftoolr/exiftool/win_exe")
Trying perl command: "" --version
Trying perl command: "perl" --version
Trying perl command: "C:\Perl64\bin\perl" --version
Trying perl command: "C:\Perl\bin\perl" --version
Trying perl command: "C:\Strawberry\perl\bin\perl" --version
Error in if (com == paste(shQuote(perl_path), shQuote(NULL))) { :
argument is of length zero
Thanks
I'm looking to use this package to check some image metadata within a shiny app.
The trick is that I have to make sure the machine running the shiny app has exiftools.
Is there a way to check that exiftool is available before attempting to run exiftoolr functionality?
Thanks!
Hi Josh
Sorry, it's me again. I am currently trying to move some picture resizing code to RStudio Workbench, which runs under Linux. I have encountered the following problem. While install_exiftool() and configure_exiftoolr() seem to work properly, exif_call() etc. do not work.
e.g.
> exif_version()
sh: 'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool': No such file or directory
Error in system2(exiftoolpath, args = args, stdout = stdout) :
error in running command
I tried some debugging and am now somehow closer to the reason, albeit not the solution of the problem.
The test_exiftool function in configure_exiftoolr() uses system(), not system2() to run the exiftool command against the OS:
_Browse[2]> test_exiftool
function (command, quiet = TRUE)
{
if (!quiet)
message("Trying exiftool command: ", command)
command_works <- suppressWarnings(suppressMessages(0 == try(**system**(command,
ignore.stdout = TRUE, ignore.stderr = TRUE, show.output.on.console = TRUE),
silent = TRUE)))
if (command_works) {
ver_string <- paste(system(command, ignore.stderr = TRUE,
intern = TRUE), collapse = "\n")
ver_number <- suppressWarnings(as.numeric(ver_string))
return(!is.na(ver_number))
}
else {
return(FALSE)
}
}
<bytecode: 0x55b476576da0>
<environment: namespace:exiftoolr>_
And this call works properly:
Browse[3]> system(command, ignore.stdout = TRUE, ignore.stderr = TRUE, show.output.on.console = TRUE)
arguments 'show.output.on.console', 'minimized' and 'invisible' are for Windows only
Browse[3]> command
[1] "'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool' -ver"
Browse[3]> system(command)
12.34
However, exif_call() etc. seem to use system2(). Now, if I understand the differrence between system and system2 correctly, system2 does not allow args in the command call ("Unlike system, command is always quoted by shQuote, so it must be a single command without arguments.")
I believe this is the reason why it fails. The exif_call() tries to run this command:
system2(exiftoolpath, args = args, stdout = stdout)
where in my case
Browse[3]> exiftoolpath
[1] "'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool'"
, while the same command but with system() instead of system2() works.
If I manually change the exiftoolpath above to just "perl" and add the real exiftool path to args, then the call works:
Browse[3]> system2(exiftoolpath, args = args, stdout = stdout)
[1] "12.34"
Browse[3]> exiftoolpath
[1] "perl"
Browse[3]> args
[1] "/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool"
[2] "-@"
[3] "'/tmp/RtmpI3pgul/args.cmd152c152d23795'"
I assume that the system call under Linux is behaving differently than under Win or MacOS (where I didn't found such issues).
Kind regards and sorry for the really lengthy description
Daniel
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.