1
Fork 0
photoview/api/scanner/process_image.go

132 lines
3.7 KiB
Go
Raw Normal View History

2020-02-02 00:29:42 +01:00
package scanner
import (
"database/sql"
2020-02-09 12:53:21 +01:00
"fmt"
2020-02-02 18:18:38 +01:00
"image"
"image/jpeg"
"log"
"os"
2020-02-02 00:29:42 +01:00
"path"
2020-02-02 18:18:38 +01:00
"strconv"
2020-02-09 12:53:21 +01:00
"strings"
2020-02-02 18:18:38 +01:00
"github.com/nfnt/resize"
2020-02-09 12:53:21 +01:00
"github.com/viktorstrate/photoview/api/graphql/models"
2020-02-09 21:25:33 +01:00
"github.com/viktorstrate/photoview/api/utils"
2020-02-02 21:44:09 +01:00
// Image decoders
_ "golang.org/x/image/bmp"
// _ "golang.org/x/image/tiff"
_ "image/gif"
_ "image/png"
2020-02-09 14:21:53 +01:00
_ "github.com/nf/cr2"
_ "golang.org/x/image/webp"
2020-02-02 00:29:42 +01:00
)
2020-02-09 14:21:53 +01:00
func ProcessImage(tx *sql.Tx, photoPath string, albumId int, content_type string) error {
2020-02-02 18:18:38 +01:00
log.Printf("Processing image: %s\n", photoPath)
2020-02-02 00:29:42 +01:00
photoName := path.Base(photoPath)
2020-02-02 18:18:38 +01:00
// Check if image already exists
row := tx.QueryRow("SELECT (photo_id) FROM photo WHERE path = ?", photoPath)
2020-02-09 12:53:21 +01:00
var photo_id int64
if err := row.Scan(&photo_id); err != sql.ErrNoRows {
2020-02-02 18:18:38 +01:00
if err == nil {
log.Printf("Image already processed: %s\n", photoPath)
return nil
} else {
return err
}
}
2020-02-09 12:53:21 +01:00
result, err := tx.Exec("INSERT INTO photo (title, path, album_id) VALUES (?, ?, ?)", photoName, photoPath, albumId)
if err != nil {
log.Printf("ERROR: Could not insert photo into database")
return err
}
photo_id, err = result.LastInsertId()
if err != nil {
return err
}
2020-02-09 14:21:53 +01:00
photo_file, err := os.Open(photoPath)
2020-02-02 18:18:38 +01:00
if err != nil {
return err
}
2020-02-09 14:21:53 +01:00
defer photo_file.Close()
2020-02-02 18:18:38 +01:00
2020-02-09 14:21:53 +01:00
image, _, err := image.Decode(photo_file)
2020-02-02 18:18:38 +01:00
if err != nil {
log.Println("ERROR: decoding image")
return err
}
2020-02-09 12:53:21 +01:00
2020-02-09 14:21:53 +01:00
photoBaseName := photoName[0 : len(photoName)-len(path.Ext(photoName))]
photoBaseExt := path.Ext(photoName)
2020-02-10 12:05:58 +01:00
// high res
highres_image_name := fmt.Sprintf("%s_%s", photoBaseName, utils.GenerateToken())
highres_image_name = strings.ReplaceAll(highres_image_name, " ", "_") + photoBaseExt
2020-02-09 14:21:53 +01:00
2020-02-10 12:05:58 +01:00
_, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, highres_image_name, image.Bounds().Max.X, image.Bounds().Max.Y, models.PhotoHighRes, content_type)
2020-02-09 12:53:21 +01:00
if err != nil {
2020-02-10 12:05:58 +01:00
log.Printf("Could not insert high-res photo url: %d, %s\n", photo_id, photoName)
2020-02-09 12:53:21 +01:00
return err
}
2020-02-10 12:05:58 +01:00
// Thumbnail
2020-02-02 18:18:38 +01:00
thumbnailImage := resize.Thumbnail(1024, 1024, image, resize.Bilinear)
if _, err := os.Stat("image-cache"); os.IsNotExist(err) {
if err := os.Mkdir("image-cache", os.ModePerm); err != nil {
log.Println("ERROR: Could not make image cache directory")
return err
}
}
// Make album cache dir
albumCachePath := path.Join("image-cache", strconv.Itoa(albumId))
if _, err := os.Stat(albumCachePath); os.IsNotExist(err) {
if err := os.Mkdir(albumCachePath, os.ModePerm); err != nil {
log.Println("ERROR: Could not make album image cache directory")
return err
}
}
// Make photo cache dir
photoCachePath := path.Join(albumCachePath, strconv.Itoa(int(photo_id)))
if _, err := os.Stat(photoCachePath); os.IsNotExist(err) {
if err := os.Mkdir(photoCachePath, os.ModePerm); err != nil {
log.Println("ERROR: Could not make photo image cache directory")
return err
}
}
2020-02-02 18:18:38 +01:00
// Save thumbnail as jpg
2020-02-09 21:25:33 +01:00
thumbnail_name := fmt.Sprintf("thumbnail_%s_%s", photoName, utils.GenerateToken())
2020-02-09 12:53:21 +01:00
thumbnail_name = strings.ReplaceAll(thumbnail_name, ".", "_")
thumbnail_name = strings.ReplaceAll(thumbnail_name, " ", "_")
thumbnail_name = thumbnail_name + ".jpg"
photo_file, err = os.Create(path.Join(photoCachePath, thumbnail_name))
2020-02-02 18:18:38 +01:00
if err != nil {
log.Println("ERROR: Could not make thumbnail file")
return err
}
2020-02-09 14:21:53 +01:00
defer photo_file.Close()
2020-02-02 18:18:38 +01:00
2020-02-09 14:21:53 +01:00
jpeg.Encode(photo_file, thumbnailImage, &jpeg.Options{Quality: 70})
2020-02-02 18:18:38 +01:00
thumbSize := thumbnailImage.Bounds().Max
2020-02-09 14:21:53 +01:00
_, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, thumbnail_name, thumbSize.X, thumbSize.Y, models.PhotoThumbnail, "image/jpeg")
2020-02-02 18:18:38 +01:00
if err != nil {
return err
}
return nil
}