Migrate to bimg & remove exif dependency
This commit is contained in:
@@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dsoprea/go-exif/v3"
|
||||
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||||
"github.com/google/uuid"
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
@@ -76,50 +77,50 @@ func deriveDeviceType(r *http.Request) model.DeviceType {
|
||||
return model.DeviceTypeUnknown
|
||||
}
|
||||
|
||||
func mediaItemFromEXIFData(filePath string) (*model.MediaItem, error) {
|
||||
rawExif, err := exif.SearchFileAndExtractExif(filePath)
|
||||
entries, _, err := exif.GetFlatExifData(rawExif, nil)
|
||||
|
||||
decLong := float64(1)
|
||||
decLat := float64(1)
|
||||
|
||||
func mediaItemFromEXIF(meta bimg.EXIF) *model.MediaItem {
|
||||
mediaItem := &model.MediaItem{}
|
||||
for _, v := range entries {
|
||||
if v.TagName == "DateTimeOriginal" {
|
||||
formattedTime, _ := time.Parse("2006:01:02 15:04:05", v.Formatted)
|
||||
mediaItem.ExifDate = &formattedTime
|
||||
} else if v.TagName == "GPSLatitude" {
|
||||
latStruct := v.Value.([]exifcommon.Rational)
|
||||
decLat *= deriveDecimalCoordinate(
|
||||
latStruct[0].Numerator/latStruct[0].Denominator,
|
||||
latStruct[1].Numerator/latStruct[1].Denominator,
|
||||
float64(latStruct[2].Numerator)/float64(latStruct[2].Denominator),
|
||||
)
|
||||
} else if v.TagName == "GPSLongitude" {
|
||||
longStruct := v.Value.([]exifcommon.Rational)
|
||||
decLong *= deriveDecimalCoordinate(
|
||||
longStruct[0].Numerator/longStruct[0].Denominator,
|
||||
longStruct[1].Numerator/longStruct[1].Denominator,
|
||||
float64(longStruct[2].Numerator)/float64(longStruct[2].Denominator),
|
||||
)
|
||||
} else if v.TagName == "GPSLatitudeRef" && v.Formatted == "S" {
|
||||
decLat *= -1
|
||||
} else if v.TagName == "GPSLongitudeRef" && v.Formatted == "W" {
|
||||
decLong *= -1
|
||||
|
||||
// DateTimeOriginal
|
||||
formattedTime, _ := time.Parse("2006:01:02 15:04:05", meta.DateTimeOriginal)
|
||||
mediaItem.ExifDate = &formattedTime
|
||||
|
||||
// GPSLatitude / Ref
|
||||
mediaItem.Latitude = deriveDecimalCoordinate(meta.GPSLatitude, meta.GPSLatitudeRef)
|
||||
|
||||
// GPSLongitude / Ref
|
||||
mediaItem.Longitude = deriveDecimalCoordinate(meta.GPSLongitude, meta.GPSLongitudeRef)
|
||||
|
||||
return mediaItem
|
||||
}
|
||||
|
||||
func deriveDecimalCoordinate(coords, direction string) *float64 {
|
||||
divideBy := [3]float64{1, 60, 3600}
|
||||
var calculatedResult float64
|
||||
|
||||
splitCoords := strings.Split(coords, " ")
|
||||
if len(splitCoords) != 3 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(splitCoords); i++ {
|
||||
splitSection := strings.Split(splitCoords[i], "/")
|
||||
numerator, err := strconv.ParseFloat(splitSection[0], 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
denominator, err := strconv.ParseFloat(splitSection[1], 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
calculatedResult += numerator / denominator / divideBy[i]
|
||||
}
|
||||
|
||||
mediaItem.Latitude = &decLat
|
||||
mediaItem.Longitude = &decLong
|
||||
|
||||
// Gross
|
||||
if err != nil && err.Error() == "no exif data" {
|
||||
return mediaItem, nil
|
||||
if direction == "S" {
|
||||
calculatedResult *= -1
|
||||
} else if direction == "W" {
|
||||
calculatedResult *= -1
|
||||
}
|
||||
|
||||
return mediaItem, err
|
||||
}
|
||||
|
||||
func deriveDecimalCoordinate(degrees, minutes uint32, seconds float64) float64 {
|
||||
return float64(degrees) + (float64(minutes) / 60) + (seconds / 3600)
|
||||
log.Info(calculatedResult)
|
||||
return &calculatedResult
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davidbyttow/govips/v2/vips"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/google/uuid"
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/generated"
|
||||
"reichard.io/imagini/graph/model"
|
||||
@@ -79,25 +80,36 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
// Create MediaItem From EXIF Data
|
||||
mediaItem, err := mediaItemFromEXIFData(filePath)
|
||||
// Load Image
|
||||
f.Seek(0, io.SeekStart)
|
||||
buffer, err := ioutil.ReadAll(f)
|
||||
newImage := bimg.NewImage(buffer)
|
||||
|
||||
// Create MediaItem from EXIF
|
||||
meta, err := newImage.Metadata()
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to extract EXIF data:", err)
|
||||
log.Error("[upload] Unable to extract metadata:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
mediaItem := mediaItemFromEXIF(meta.EXIF)
|
||||
|
||||
// Use Vips for Width & Height
|
||||
f.Seek(0, io.SeekStart)
|
||||
image, err := vips.NewImageFromReader(f)
|
||||
// Determine Image Size
|
||||
imageSize, err := newImage.Size()
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to extract dimension data:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
if meta.Orientation > 4 {
|
||||
mediaItem.Width = imageSize.Height
|
||||
mediaItem.Height = imageSize.Width
|
||||
} else {
|
||||
mediaItem.Width = imageSize.Width
|
||||
mediaItem.Height = imageSize.Height
|
||||
}
|
||||
|
||||
// Add Additional MediaItem Fields
|
||||
mediaItem.ID = mediaItemID
|
||||
mediaItem.Width = image.Width()
|
||||
mediaItem.Height = image.Height()
|
||||
mediaItem.UserID = userID
|
||||
mediaItem.IsVideo = isVideo
|
||||
mediaItem.FileName = fileName
|
||||
|
||||
Reference in New Issue
Block a user