1
Fork 0
photoview/api/scanner/exif/exif_parser_external.go

207 lines
4.8 KiB
Go

package exif
import (
"log"
"regexp"
"strconv"
"time"
"github.com/barasher/go-exiftool"
"github.com/photoview/photoview/api/graphql/models"
)
type externalExifParser struct{}
func (p *externalExifParser) ParseExif(media *models.Media) (returnExif *models.MediaEXIF, returnErr error) {
// Init ExifTool
et, err := exiftool.NewExiftool()
if err != nil {
log.Printf("Error initializing ExifTool: %s\n", err)
return nil, err
}
defer et.Close()
fileInfos := et.ExtractMetadata(media.Path)
newExif := models.MediaEXIF{}
for _, fileInfo := range fileInfos {
if fileInfo.Err != nil {
log.Printf("Fileinfo error\n")
continue
}
// Get camera model
model, err := fileInfo.GetString("Model")
if err == nil {
log.Printf("Camera model: %v", model)
newExif.Camera = &model
}
// Get Camera make
make, err := fileInfo.GetString("Make")
if err == nil {
log.Printf("Camera make: %v", make)
newExif.Maker = &make
}
// Get lens
lens, err := fileInfo.GetString("LensModel")
if err == nil {
log.Printf("Lens: %v", lens)
newExif.Lens = &lens
}
//Get time of photo
date, err := fileInfo.GetString("DateTimeOriginal")
if err == nil {
log.Printf("Date shot: %s", date)
layout := "2006:01:02 15:04:05"
dateTime, err := time.Parse(layout, date)
if err == nil {
newExif.DateShot = &dateTime
}
}
// Get exposure time
exposureTime, err := fileInfo.GetString("ExposureTime")
if err == nil {
log.Printf("Exposure time: %s", exposureTime)
newExif.Exposure = &exposureTime
}
// Get aperture
aperture, err := fileInfo.GetFloat("Aperture")
if err == nil {
log.Printf("Aperture: %f", aperture)
newExif.Aperture = &aperture
}
// Get ISO
iso, err := fileInfo.GetInt("ISO")
if err == nil {
log.Printf("ISO: %d", iso)
newExif.Iso = &iso
}
// Get focal length
focalLen, err := fileInfo.GetString("FocalLength")
if err == nil {
log.Printf("Focal length: %s", focalLen)
reg, err := regexp.Compile("[0-9.]+")
focalLenStr := reg.FindString(focalLen)
focalLenFloat, err := strconv.ParseFloat(focalLenStr, 64)
if err == nil {
newExif.FocalLength = &focalLenFloat
}
}
// Get flash info
flash, err := fileInfo.GetString("Flash")
if err == nil {
log.Printf("Flash: %s", flash)
newExif.Flash = &flash
}
// Get orientation
orientation, err := fileInfo.GetString("Orientation")
log.Printf("Orientation: %s", orientation)
if err == nil {
if orientation == "Horizontal (normal)" {
var orientationInt int64 = 0
newExif.Orientation = &orientationInt
} else {
reg, err := regexp.Compile("CCW")
if err == nil {
if reg.MatchString(orientation) {
//Counter clockwise
reg, err := regexp.Compile("[0-9.]+")
orientationStr := reg.FindString(orientation)
orientationInt, err := strconv.ParseInt(orientationStr, 10, 64)
if err == nil {
log.Printf("Orientation: %d", orientationInt)
newExif.Orientation = &orientationInt
}
} else {
// Clockwise
reg, err := regexp.Compile("[0-9.]+")
orientationStr := reg.FindString(orientation)
orientationInt, err := strconv.ParseInt(orientationStr, 10, 64)
if err == nil {
orientationInt = orientationInt * -1
log.Printf("Orientation: %d", orientationInt)
newExif.Orientation = &orientationInt
}
}
}
}
}
// Get exposure program
expProgram, err := fileInfo.GetString("ExposureProgram")
if err == nil {
log.Printf("Exposure Program: %s", expProgram)
newExif.ExposureProgram = &expProgram
}
// GPS coordinates - longitude
longitudeRaw, err := fileInfo.GetString("GPSLongitude")
if err == nil {
log.Printf("GPS longitude: %s", longitudeRaw)
value, err := ConvertCoodinateToFloat(longitudeRaw)
if err == nil {
newExif.GPSLongitude = &value
}
}
// GPS coordinates - latitude
latitudeRaw, err := fileInfo.GetString("GPSLatitude")
if err == nil {
log.Printf("GPS latitude: %s", latitudeRaw)
value, err := ConvertCoodinateToFloat(latitudeRaw)
if err == nil {
newExif.GPSLatitude = &value
}
}
}
returnExif = &newExif
return
}
func ConvertCoodinateToFloat(coordinate string) (value float64, err error) {
reg, err := regexp.Compile("[0-9.]+")
if err != nil {
return 0, err
}
coordinateStr := reg.FindAllString(coordinate, -1)
log.Printf("GPS: %s length: %d\n", coordinateStr, len(coordinateStr))
if len(coordinateStr) != 3 {
return 0, err
}
deg, err := strconv.ParseFloat(coordinateStr[0], 64)
if err != nil {
return 0, err
}
minute, err := strconv.ParseFloat(coordinateStr[1], 64)
if err != nil {
return 0, err
}
second, err := strconv.ParseFloat(coordinateStr[2], 64)
if err != nil {
return 0, err
}
var multiplier float64 = 1
if deg < 0 {
multiplier = -1
}
value = (deg + minute / 60 + second / 3600) * multiplier
return value, nil
}