Reading EXIF appears easy under Java with Drew Noakes’s metadata-extractor but that library doesn't write EXIF data. There's the javax.imageio package, but that seems to be low level (ie, hard to use). I want a quick and dirty hack. So I'll use metadata-extractor to get the dates and call out to exiv2 to set the dates.
Of course, Java often brings up things you can stumble over, and this was getting the exiv2 command to run. I decided to use ProcessBuilder from java.lang (which, surprisingly, Groovy didn't seem to auto import), but it took a while to work out how to get it to launch an exiv2 command correctly (if at all). At a unix command line, in order to set the Original Date Time, you'd use something like:
exiv2 -M"set Exif.Photo.DateTimeDigitized String 2007:03:27 07:53:16" ./photos/HPIM0059.JPG
It took ages to work out that I had to split the -M from the set command and that I should not quote the set command, so that the call to ProcessBuilder is along the lines of
Process p = new java.lang.ProcessBuilder("exiv2", "-M", "set Exif.Photo.DateTimeOriginal String 2007:03:27 07:53:16", "./photos/HPIM0059.JPG").start()
Here's the code. Use at your own risk (remember, this script modifies files, so it could destroy something), and you'll proabably need to modify it to get it to work anyway.
import com.drew.metadata.*
import com.drew.imaging.jpeg.*
import com.drew.metadata.exif.ExifDirectory
import org.joda.time.*
import org.joda.time.format.*
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy:MM:dd HH:mm:ss");
photoDir = new File("photos")
photoDir.eachFile { file ->
Metadata metadata = JpegMetadataReader.readMetadata(file);
com.drew.metadata.exif.ExifDirectory exifDir = metadata.getDirectory(com.drew.metadata.exif.ExifDirectory)
DateTime original = new org.joda.time.DateTime(exifDir.getDate(ExifDirectory.TAG_DATETIME_ORIGINAL))
String newOriginal = fmt.print(original.plusYears(1))
DateTime digitized = new org.joda.time.DateTime(exifDir.getDate(ExifDirectory.TAG_DATETIME_DIGITIZED))
String newDigitized = fmt.print(digitized.plusYears(1))
String fn = "~/projects/photo/fixdate/photos/${file.name}"
String exiv2OCmd = "set Exif.Photo.DateTimeOriginal String ${newOriginal}"
String exiv2DCmd = "set Exif.Photo.DateTimeDigitized String ${newDigitized}"
println exiv2OCmd
Process p = new java.lang.ProcessBuilder("exiv2", "-M", exiv2OCmd, fn).start()
p.errorStream.eachLine { println it }
Process q = new java.lang.ProcessBuilder("exiv2", "-M", exiv2DCmd, fn).start()
q.errorStream.eachLine { println it }
//might as well set the last modified date
file.setLastModified(original.plusYears(1).toDate().time)
}
No comments:
Post a Comment