/src/ExifMiner.groovy
https://github.com/frederic-schmaljohann/GroovyExifMiner · Groovy · 127 lines · 72 code · 15 blank · 40 comment · 8 complexity · cfe5823d45e18927b1d7fdc0c90993ba MD5 · raw file
- import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
- import com.drew.imaging.ImageMetadataReader
- import com.drew.metadata.Metadata
- import com.drew.metadata.exif.ExifIFD0Directory;
- import com.drew.metadata.exif.ExifSubIFDDirectory
- /**
- * Prints a bunch of stats for Exif related data
- * using metadata-extractor
- *
- * @author Frederic Schmaljohann
- */
- class ExifAnalyzer {
- /**
- * File extension of image files
- */
- static final String REGEX_PICTURE_FILE = /.*jpg|.*cr2/
- /**
- * Directory to be traversed (recursively)
- */
- static final String IMAGE_DIR = 'SOME_DIR'
- static final String SEPARATOR = '==='
-
- DescriptiveStatistics focalLengths = new DescriptiveStatistics()
- DescriptiveStatistics isos = new DescriptiveStatistics()
- DescriptiveStatistics apertures = new DescriptiveStatistics()
- /**
- * Computes descriptive stats for focal length, iso and aperture values
- * @return
- */
- def computeStats() {
- new File(IMAGE_DIR).traverse {
- if (it.isFile() && it.canonicalPath.toLowerCase() ==~ REGEX_PICTURE_FILE) {
- try {
- extractData(it.canonicalPath)
- }
- catch (e) {
- println e.message
- }
- }
- }
- }
- private printStats() {
- println SEPARATOR + 'Focal length' + SEPARATOR
- printStats(focalLengths)
- println '\n' + SEPARATOR + 'ISO' + SEPARATOR
- printStats(isos)
- println '\n' + SEPARATOR + 'Apertures' + SEPARATOR
- printStats(apertures)
- }
- /**
- * Extract the data and put it into statistics
- * @param pictureFile
- * @return
- */
- private extractData(String pictureFile) {
- Metadata meta = ImageMetadataReader.readMetadata(new File(pictureFile))
- ExifSubIFDDirectory dir = meta.getDirectory(ExifSubIFDDirectory.class)
- ExifIFD0Directory dir2 = meta.getDirectory(ExifIFD0Directory.class)
- focalLengths.addValue(Double.parseDouble(dir.getString(ExifSubIFDDirectory.TAG_FOCAL_LENGTH)))
- isos.addValue(Double.parseDouble(dir.getString(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT)))
- double aperture = computeAperture(dir.getString(ExifSubIFDDirectory.TAG_APERTURE))
- apertures.addValue(aperture)
- }
-
- /**
- * Compute aperture
- * @param apertureString
- * @return
- */
- def computeAperture(String apertureString) {
- Math.round(Math.pow(2, (parseFraction() / 2)) * 10) / 10
- }
- /**
- * Print statistics
- * @param stats
- * @return
- */
- def printStats(DescriptiveStatistics stats) {
- println stats
- printFrequencies(stats.sortedValues)
- }
- /**
- * parses a double or fraction, e.g. 127/56 or 12.4
- * @param stringToParse
- * @return
- */
- def double parseFraction(String stringToParse) {
- if (stringToParse.indexOf('/') == -1) {
- return Double.parseDouble(stringToParse)
- }
- double d = Double.parseDouble(stringToParse.substring(0, stringToParse.indexOf('/')))
- d /= Double.parseDouble(stringToParse.substring(stringToParse.indexOf('/')+1))
- }
- /**
- * Print the frequencies
- * @param sortedArray
- */
- def printFrequencies(double[] sortedArray) {
- double currValue = sortedArray[0]
- int currCounter = 1
- for (int i=0;i < sortedArray.size(); i++) {
- if (currValue == sortedArray[i]) {
- currCounter++
- }
- else {
- println currValue + '->' + currCounter
- currValue = sortedArray[i]
- }
- }
- }
- }
- ExifAnalyzer ee = new ExifAnalyzer()
- ee.computeStats()
- ee.printStats()