2020-02-23 18:00:08 +01:00
|
|
|
package scanner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
|
|
|
|
2020-12-17 22:51:43 +01:00
|
|
|
"github.com/photoview/photoview/api/graphql/models"
|
2021-02-16 11:27:28 +01:00
|
|
|
"github.com/photoview/photoview/api/scanner/image_helpers"
|
2020-12-17 22:51:43 +01:00
|
|
|
"github.com/photoview/photoview/api/utils"
|
2020-05-14 14:35:08 +02:00
|
|
|
"github.com/pkg/errors"
|
2020-11-23 19:59:01 +01:00
|
|
|
"gorm.io/gorm"
|
2020-02-23 18:00:08 +01:00
|
|
|
|
|
|
|
// Image decoders
|
|
|
|
_ "image/gif"
|
|
|
|
_ "image/png"
|
|
|
|
|
2020-03-02 16:32:24 +01:00
|
|
|
_ "golang.org/x/image/bmp"
|
|
|
|
_ "golang.org/x/image/tiff"
|
2020-02-23 18:00:08 +01:00
|
|
|
_ "golang.org/x/image/webp"
|
|
|
|
)
|
|
|
|
|
2020-07-10 14:26:19 +02:00
|
|
|
// Higher order function used to check if MediaURL for a given MediaPurpose exists
|
2020-11-30 21:29:49 +01:00
|
|
|
func makePhotoURLChecker(tx *gorm.DB, mediaID int) func(purpose models.MediaPurpose) (*models.MediaURL, error) {
|
2020-07-10 14:26:19 +02:00
|
|
|
return func(purpose models.MediaPurpose) (*models.MediaURL, error) {
|
2020-11-30 21:29:49 +01:00
|
|
|
var mediaURL []*models.MediaURL
|
2020-11-24 11:46:49 +01:00
|
|
|
|
2020-12-08 16:24:08 +01:00
|
|
|
result := tx.Where("purpose = ?", purpose).Where("media_id = ?", mediaID).Find(&mediaURL)
|
2020-11-30 21:29:49 +01:00
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.RowsAffected > 0 {
|
|
|
|
return mediaURL[0], nil
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
2020-11-30 21:29:49 +01:00
|
|
|
return nil, nil
|
|
|
|
}
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
func generateUniqueMediaNamePrefixed(prefix string, mediaPath string, extension string) string {
|
|
|
|
mediaName := fmt.Sprintf("%s_%s_%s", prefix, path.Base(mediaPath), utils.GenerateToken())
|
|
|
|
mediaName = models.SanitizeMediaName(mediaName)
|
|
|
|
mediaName = mediaName + extension
|
|
|
|
return mediaName
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateUniqueMediaName(mediaPath string) string {
|
|
|
|
|
|
|
|
filename := path.Base(mediaPath)
|
|
|
|
baseName := filename[0 : len(filename)-len(path.Ext(filename))]
|
|
|
|
baseExt := path.Ext(filename)
|
|
|
|
|
|
|
|
mediaName := fmt.Sprintf("%s_%s", baseName, utils.GenerateToken())
|
|
|
|
mediaName = models.SanitizeMediaName(mediaName) + baseExt
|
|
|
|
|
|
|
|
return mediaName
|
|
|
|
}
|
|
|
|
|
2020-11-23 19:59:01 +01:00
|
|
|
func ProcessMedia(tx *gorm.DB, media *models.Media) (bool, error) {
|
2020-07-11 13:13:31 +02:00
|
|
|
imageData := EncodeMediaData{
|
2020-07-10 14:26:19 +02:00
|
|
|
media: media,
|
2020-07-10 12:58:11 +02:00
|
|
|
}
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2020-07-10 12:58:11 +02:00
|
|
|
contentType, err := imageData.ContentType()
|
|
|
|
if err != nil {
|
2020-07-10 14:26:19 +02:00
|
|
|
return false, errors.Wrapf(err, "get content-type of media (%s)", media.Path)
|
2020-07-10 12:58:11 +02:00
|
|
|
}
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2020-07-10 14:26:19 +02:00
|
|
|
// Make sure media cache directory exists
|
|
|
|
mediaCachePath, err := makeMediaCacheDir(media)
|
2020-07-10 12:58:11 +02:00
|
|
|
if err != nil {
|
|
|
|
return false, errors.Wrap(err, "cache directory error")
|
|
|
|
}
|
2020-06-23 15:13:07 +02:00
|
|
|
|
2020-07-10 12:58:11 +02:00
|
|
|
if contentType.isVideo() {
|
|
|
|
return processVideo(tx, &imageData, mediaCachePath)
|
|
|
|
} else {
|
|
|
|
return processPhoto(tx, &imageData, mediaCachePath)
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
2020-07-10 12:58:11 +02:00
|
|
|
}
|
|
|
|
|
2020-11-23 19:59:01 +01:00
|
|
|
func processPhoto(tx *gorm.DB, imageData *EncodeMediaData, photoCachePath *string) (bool, error) {
|
2020-07-10 12:58:11 +02:00
|
|
|
|
2020-07-10 14:26:19 +02:00
|
|
|
photo := imageData.media
|
2020-07-10 12:58:11 +02:00
|
|
|
|
|
|
|
log.Printf("Processing photo: %s\n", photo.Path)
|
|
|
|
|
|
|
|
didProcess := false
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2020-11-30 21:29:49 +01:00
|
|
|
photoURLFromDB := makePhotoURLChecker(tx, photo.ID)
|
2020-02-23 18:00:08 +01:00
|
|
|
|
|
|
|
// original photo url
|
2020-11-30 21:29:49 +01:00
|
|
|
origURL, err := photoURLFromDB(models.MediaOriginal)
|
2020-02-23 18:00:08 +01:00
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, err
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Thumbnail
|
2020-11-30 21:29:49 +01:00
|
|
|
thumbURL, err := photoURLFromDB(models.PhotoThumbnail)
|
2020-02-23 18:00:08 +01:00
|
|
|
if err != nil {
|
2020-07-10 12:58:11 +02:00
|
|
|
return false, errors.Wrap(err, "error processing photo thumbnail")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Highres
|
2020-11-30 21:29:49 +01:00
|
|
|
highResURL, err := photoURLFromDB(models.PhotoHighRes)
|
2020-02-23 18:00:08 +01:00
|
|
|
if err != nil {
|
2020-07-10 12:58:11 +02:00
|
|
|
return false, errors.Wrap(err, "error processing photo highres")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
2021-02-16 11:27:28 +01:00
|
|
|
var photoDimensions *image_helpers.PhotoDimensions
|
2020-05-15 16:36:02 +02:00
|
|
|
var baseImagePath string = photo.Path
|
|
|
|
|
2020-11-19 08:21:35 +01:00
|
|
|
mediaType, err := getMediaType(photo.Path)
|
|
|
|
if err != nil {
|
|
|
|
return false, errors.Wrap(err, "could determine if media was photo or video")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate high res jpeg
|
2020-02-23 18:00:08 +01:00
|
|
|
if highResURL == nil {
|
2020-02-26 21:23:13 +01:00
|
|
|
|
|
|
|
contentType, err := imageData.ContentType()
|
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, err
|
2020-02-26 21:23:13 +01:00
|
|
|
}
|
|
|
|
|
2020-05-15 16:36:02 +02:00
|
|
|
if !contentType.isWebCompatible() {
|
2020-06-23 15:18:13 +02:00
|
|
|
didProcess = true
|
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
highresName := generateUniqueMediaNamePrefixed("highres", photo.Path, ".jpg")
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
baseImagePath = path.Join(*photoCachePath, highresName)
|
2020-05-15 16:36:02 +02:00
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
newHighResURL, err := generateSaveHighResJPEG(tx, photo, imageData, highresName, baseImagePath, nil)
|
2020-02-23 18:00:08 +01:00
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, err
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
2020-12-15 01:25:30 +01:00
|
|
|
|
|
|
|
highResURL = newHighResURL
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
2020-05-14 14:35:08 +02:00
|
|
|
} else {
|
|
|
|
// Verify that highres photo still exists in cache
|
2020-07-10 14:26:19 +02:00
|
|
|
baseImagePath = path.Join(*photoCachePath, highResURL.MediaName)
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2020-05-15 16:36:02 +02:00
|
|
|
if _, err := os.Stat(baseImagePath); os.IsNotExist(err) {
|
2020-07-10 14:26:19 +02:00
|
|
|
fmt.Printf("High-res photo found in database but not in cache, re-encoding photo to cache: %s\n", highResURL.MediaName)
|
2020-06-23 15:13:07 +02:00
|
|
|
didProcess = true
|
2020-02-23 18:00:08 +01:00
|
|
|
|
2020-05-15 16:36:02 +02:00
|
|
|
err = imageData.EncodeHighRes(tx, baseImagePath)
|
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, errors.Wrap(err, "creating high-res cached image")
|
2020-05-15 16:36:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save original photo to database
|
|
|
|
if origURL == nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
didProcess = true
|
|
|
|
|
2020-05-15 16:36:02 +02:00
|
|
|
// Make sure photo dimensions is set
|
|
|
|
if photoDimensions == nil {
|
2021-02-16 11:27:28 +01:00
|
|
|
photoDimensions, err = image_helpers.GetPhotoDimensions(baseImagePath)
|
2020-05-15 15:23:21 +02:00
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, err
|
2020-05-15 15:23:21 +02:00
|
|
|
}
|
2020-05-15 16:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if err = saveOriginalPhotoToDB(tx, photo, imageData, photoDimensions); err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, errors.Wrap(err, "saving original photo to database")
|
2020-05-15 16:36:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save thumbnail to cache
|
|
|
|
if thumbURL == nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
didProcess = true
|
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
thumbnailName := generateUniqueMediaNamePrefixed("thumbnail", photo.Path, ".jpg")
|
2020-05-15 16:36:02 +02:00
|
|
|
|
2021-01-27 18:00:37 +01:00
|
|
|
newThumbURL, err := generateSaveThumbnailJPEG(tx, photo, thumbnailName, photoCachePath, baseImagePath, nil)
|
2020-05-15 16:36:02 +02:00
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, err
|
2020-05-15 16:36:02 +02:00
|
|
|
}
|
2020-12-15 01:25:30 +01:00
|
|
|
|
|
|
|
thumbURL = newThumbURL
|
2020-05-15 16:36:02 +02:00
|
|
|
} else {
|
|
|
|
// Verify that thumbnail photo still exists in cache
|
2020-07-10 14:26:19 +02:00
|
|
|
thumbPath := path.Join(*photoCachePath, thumbURL.MediaName)
|
2020-05-15 16:36:02 +02:00
|
|
|
|
|
|
|
if _, err := os.Stat(thumbPath); os.IsNotExist(err) {
|
2020-06-23 15:13:07 +02:00
|
|
|
didProcess = true
|
2020-07-10 14:26:19 +02:00
|
|
|
fmt.Printf("Thumbnail photo found in database but not in cache, re-encoding photo to cache: %s\n", thumbURL.MediaName)
|
2020-05-15 16:36:02 +02:00
|
|
|
|
|
|
|
_, err := EncodeThumbnail(baseImagePath, thumbPath)
|
2020-02-23 18:00:08 +01:00
|
|
|
if err != nil {
|
2020-06-23 15:13:07 +02:00
|
|
|
return false, errors.Wrap(err, "could not create thumbnail cached image")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-15 01:25:30 +01:00
|
|
|
if mediaType.isRaw() {
|
|
|
|
err = processRawSideCar(tx, imageData, highResURL, thumbURL, photoCachePath)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
counterpartFile := scanForCompressedCounterpartFile(photo.Path)
|
|
|
|
if counterpartFile != nil {
|
|
|
|
photo.CounterpartPath = counterpartFile
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 15:13:07 +02:00
|
|
|
return didProcess, nil
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
|
2020-12-06 15:24:15 +01:00
|
|
|
func makeMediaCacheDir(media *models.Media) (*string, error) {
|
2020-02-23 18:00:08 +01:00
|
|
|
|
|
|
|
// Make root cache dir if not exists
|
2021-02-15 17:35:28 +01:00
|
|
|
if _, err := os.Stat(utils.MediaCachePath()); os.IsNotExist(err) {
|
|
|
|
if err := os.Mkdir(utils.MediaCachePath(), os.ModePerm); err != nil {
|
2020-07-10 12:58:11 +02:00
|
|
|
return nil, errors.Wrap(err, "could not make root image cache directory")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make album cache dir if not exists
|
2021-02-15 17:35:28 +01:00
|
|
|
albumCachePath := path.Join(utils.MediaCachePath(), strconv.Itoa(int(media.AlbumID)))
|
2020-02-23 18:00:08 +01:00
|
|
|
if _, err := os.Stat(albumCachePath); os.IsNotExist(err) {
|
|
|
|
if err := os.Mkdir(albumCachePath, os.ModePerm); err != nil {
|
2020-07-10 12:58:11 +02:00
|
|
|
return nil, errors.Wrap(err, "could not make album image cache directory")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make photo cache dir if not exists
|
2020-12-06 15:24:15 +01:00
|
|
|
photoCachePath := path.Join(albumCachePath, strconv.Itoa(int(media.ID)))
|
2020-02-23 18:00:08 +01:00
|
|
|
if _, err := os.Stat(photoCachePath); os.IsNotExist(err) {
|
|
|
|
if err := os.Mkdir(photoCachePath, os.ModePerm); err != nil {
|
2020-07-10 12:58:11 +02:00
|
|
|
return nil, errors.Wrap(err, "could not make photo image cache directory")
|
2020-02-23 18:00:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &photoCachePath, nil
|
|
|
|
}
|
2020-05-15 16:36:02 +02:00
|
|
|
|
2021-02-16 11:27:28 +01:00
|
|
|
func saveOriginalPhotoToDB(tx *gorm.DB, photo *models.Media, imageData *EncodeMediaData, photoDimensions *image_helpers.PhotoDimensions) error {
|
2021-01-27 18:00:37 +01:00
|
|
|
originalImageName := generateUniqueMediaName(photo.Path)
|
2020-05-15 16:36:02 +02:00
|
|
|
|
|
|
|
contentType, err := imageData.ContentType()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-11 22:18:15 +02:00
|
|
|
fileStats, err := os.Stat(photo.Path)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "reading file stats of original photo")
|
|
|
|
}
|
|
|
|
|
2020-11-24 11:46:49 +01:00
|
|
|
mediaURL := models.MediaURL{
|
2021-02-15 17:35:28 +01:00
|
|
|
Media: photo,
|
2021-01-27 18:00:37 +01:00
|
|
|
MediaName: originalImageName,
|
2020-11-24 11:46:49 +01:00
|
|
|
Width: photoDimensions.Width,
|
|
|
|
Height: photoDimensions.Height,
|
|
|
|
Purpose: models.MediaOriginal,
|
|
|
|
ContentType: string(*contentType),
|
|
|
|
FileSize: fileStats.Size(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Create(&mediaURL).Error; err != nil {
|
2021-01-27 18:00:37 +01:00
|
|
|
return errors.Wrapf(err, "inserting original photo url: %d, %s", photo.ID, photo.Title)
|
2020-05-15 16:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2020-11-19 08:21:35 +01:00
|
|
|
|
2020-12-17 23:18:00 +01:00
|
|
|
func generateSaveHighResJPEG(tx *gorm.DB, media *models.Media, imageData *EncodeMediaData, highres_name string, imagePath string, mediaURL *models.MediaURL) (*models.MediaURL, error) {
|
2020-11-19 08:21:35 +01:00
|
|
|
|
|
|
|
err := imageData.EncodeHighRes(tx, imagePath)
|
|
|
|
if err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrap(err, "creating high-res cached image")
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2021-02-16 11:27:28 +01:00
|
|
|
photoDimensions, err := image_helpers.GetPhotoDimensions(imagePath)
|
2020-11-19 08:21:35 +01:00
|
|
|
if err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, err
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fileStats, err := os.Stat(imagePath)
|
|
|
|
if err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrap(err, "reading file stats of highres photo")
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2020-11-24 11:46:49 +01:00
|
|
|
if mediaURL == nil {
|
|
|
|
|
|
|
|
mediaURL = &models.MediaURL{
|
|
|
|
MediaID: media.ID,
|
|
|
|
MediaName: highres_name,
|
|
|
|
Width: photoDimensions.Width,
|
|
|
|
Height: photoDimensions.Height,
|
|
|
|
Purpose: models.PhotoHighRes,
|
|
|
|
ContentType: "image/jpeg",
|
|
|
|
FileSize: fileStats.Size(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Create(&mediaURL).Error; err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrapf(err, "could not insert highres media url (%d, %s)", media.ID, highres_name)
|
2020-11-24 11:46:49 +01:00
|
|
|
}
|
2020-11-19 08:21:35 +01:00
|
|
|
} else {
|
2020-11-24 11:46:49 +01:00
|
|
|
mediaURL.Width = photoDimensions.Width
|
|
|
|
mediaURL.Height = photoDimensions.Height
|
|
|
|
mediaURL.FileSize = fileStats.Size()
|
|
|
|
|
|
|
|
if err := tx.Save(&mediaURL).Error; err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrapf(err, "could not update media url after side car changes (%d, %s)", media.ID, highres_name)
|
2020-11-24 11:46:49 +01:00
|
|
|
}
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2020-12-15 01:25:30 +01:00
|
|
|
return mediaURL, nil
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2020-12-15 01:25:30 +01:00
|
|
|
func generateSaveThumbnailJPEG(tx *gorm.DB, media *models.Media, thumbnail_name string, photoCachePath *string, baseImagePath string, mediaURL *models.MediaURL) (*models.MediaURL, error) {
|
2020-11-19 08:21:35 +01:00
|
|
|
thumbOutputPath := path.Join(*photoCachePath, thumbnail_name)
|
|
|
|
|
|
|
|
thumbSize, err := EncodeThumbnail(baseImagePath, thumbOutputPath)
|
|
|
|
if err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrap(err, "could not create thumbnail cached image")
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fileStats, err := os.Stat(thumbOutputPath)
|
|
|
|
if err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrap(err, "reading file stats of thumbnail photo")
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2020-11-24 11:46:49 +01:00
|
|
|
if mediaURL == nil {
|
|
|
|
|
|
|
|
mediaURL = &models.MediaURL{
|
|
|
|
MediaID: media.ID,
|
|
|
|
MediaName: thumbnail_name,
|
|
|
|
Width: thumbSize.Width,
|
|
|
|
Height: thumbSize.Height,
|
|
|
|
Purpose: models.PhotoThumbnail,
|
|
|
|
ContentType: "image/jpeg",
|
|
|
|
FileSize: fileStats.Size(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Create(&mediaURL).Error; err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrapf(err, "could not insert thumbnail media url (%d, %s)", media.ID, thumbnail_name)
|
2020-11-24 11:46:49 +01:00
|
|
|
}
|
2020-11-19 08:21:35 +01:00
|
|
|
} else {
|
2020-11-24 11:46:49 +01:00
|
|
|
mediaURL.Width = thumbSize.Width
|
|
|
|
mediaURL.Height = thumbSize.Height
|
|
|
|
mediaURL.FileSize = fileStats.Size()
|
|
|
|
|
|
|
|
if err := tx.Save(&mediaURL).Error; err != nil {
|
2020-12-15 01:25:30 +01:00
|
|
|
return nil, errors.Wrapf(err, "could not update media url after side car changes (%d, %s)", media.ID, thumbnail_name)
|
2020-11-24 11:46:49 +01:00
|
|
|
}
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
2020-11-24 11:46:49 +01:00
|
|
|
|
2020-12-15 01:25:30 +01:00
|
|
|
return mediaURL, nil
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
|
2020-11-24 11:46:49 +01:00
|
|
|
func processRawSideCar(tx *gorm.DB, imageData *EncodeMediaData, highResURL *models.MediaURL, thumbURL *models.MediaURL, photoCachePath *string) error {
|
2020-11-19 08:21:35 +01:00
|
|
|
photo := imageData.media
|
|
|
|
sideCarFileHasChanged := false
|
|
|
|
var currentFileHash *string
|
|
|
|
currentSideCarPath := scanForSideCarFile(photo.Path)
|
|
|
|
|
|
|
|
if currentSideCarPath != nil {
|
2020-11-22 23:42:42 +01:00
|
|
|
currentFileHash = hashSideCarFile(currentSideCarPath)
|
2020-11-19 08:21:35 +01:00
|
|
|
if photo.SideCarHash == nil || *photo.SideCarHash != *currentFileHash {
|
|
|
|
sideCarFileHasChanged = true
|
|
|
|
}
|
|
|
|
} else if photo.SideCarPath != nil { // sidecar has been deleted since last scan
|
|
|
|
sideCarFileHasChanged = true
|
|
|
|
}
|
2020-11-24 11:46:49 +01:00
|
|
|
|
2020-11-19 08:21:35 +01:00
|
|
|
if sideCarFileHasChanged {
|
|
|
|
fmt.Printf("Detected changed sidecar file for %s recreating JPG's to reflect changes\n", photo.Path)
|
|
|
|
|
|
|
|
// update high res image may be cropped so dimentions and file size can change
|
|
|
|
baseImagePath := path.Join(*photoCachePath, highResURL.MediaName) // update base image path for thumbnail
|
|
|
|
tempHighResPath := baseImagePath + ".hold"
|
|
|
|
os.Rename(baseImagePath, tempHighResPath)
|
2020-12-15 01:25:30 +01:00
|
|
|
_, err := generateSaveHighResJPEG(tx, photo, imageData, highResURL.MediaName, baseImagePath, highResURL)
|
2020-11-19 08:21:35 +01:00
|
|
|
if err != nil {
|
|
|
|
os.Rename(tempHighResPath, baseImagePath)
|
|
|
|
return errors.Wrap(err, "recreating high-res cached image")
|
|
|
|
}
|
|
|
|
os.Remove(tempHighResPath)
|
|
|
|
|
|
|
|
// update thumbnail image may be cropped so dimentions and file size can change
|
|
|
|
thumbPath := path.Join(*photoCachePath, thumbURL.MediaName)
|
|
|
|
tempThumbPath := thumbPath + ".hold" // hold onto the original image incase for some reason we fail to recreate one with the new settings
|
|
|
|
os.Rename(thumbPath, tempThumbPath)
|
2020-12-15 01:25:30 +01:00
|
|
|
_, err = generateSaveThumbnailJPEG(tx, photo, thumbURL.MediaName, photoCachePath, baseImagePath, thumbURL)
|
2020-11-19 08:21:35 +01:00
|
|
|
if err != nil {
|
|
|
|
os.Rename(tempThumbPath, thumbPath)
|
|
|
|
return errors.Wrap(err, "recreating thumbnail cached image")
|
|
|
|
}
|
|
|
|
os.Remove(tempThumbPath)
|
|
|
|
|
2020-11-24 11:46:49 +01:00
|
|
|
photo.SideCarHash = currentFileHash
|
|
|
|
photo.SideCarPath = currentSideCarPath
|
|
|
|
|
2020-11-19 08:21:35 +01:00
|
|
|
// save new side car hash
|
2020-11-24 11:46:49 +01:00
|
|
|
if err := tx.Save(&photo).Error; err != nil {
|
2020-11-22 23:42:42 +01:00
|
|
|
return errors.Wrapf(err, "could not update side car hash for media: %s", photo.Path)
|
2020-11-19 08:21:35 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-24 11:46:49 +01:00
|
|
|
|
2020-11-19 08:21:35 +01:00
|
|
|
return nil
|
|
|
|
}
|