2020-02-02 00:29:42 +01:00
|
|
|
package scanner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2020-02-02 18:18:38 +01:00
|
|
|
"image"
|
|
|
|
"image/jpeg"
|
|
|
|
"log"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
2020-02-02 00:29:42 +01:00
|
|
|
"path"
|
2020-02-02 18:18:38 +01:00
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/nfnt/resize"
|
2020-02-02 21:44:09 +01:00
|
|
|
|
|
|
|
// Image decoders
|
|
|
|
_ "golang.org/x/image/bmp"
|
|
|
|
// _ "golang.org/x/image/tiff"
|
|
|
|
_ "github.com/nf/cr2"
|
|
|
|
_ "golang.org/x/image/webp"
|
|
|
|
_ "image/gif"
|
|
|
|
_ "image/png"
|
2020-02-02 00:29:42 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func ProcessImage(tx *sql.Tx, photoPath string, albumId int) 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)
|
|
|
|
var id int
|
|
|
|
if err := row.Scan(&id); err != sql.ErrNoRows {
|
|
|
|
if err == nil {
|
|
|
|
log.Printf("Image already processed: %s\n", photoPath)
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
thumbFile, err := os.Open(photoPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer thumbFile.Close()
|
|
|
|
|
|
|
|
image, _, err := image.Decode(thumbFile)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("ERROR: decoding image")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Generate image token name
|
|
|
|
thumbnailToken := generateToken()
|
|
|
|
originalToken := generateToken()
|
|
|
|
|
|
|
|
// Save thumbnail as jpg
|
|
|
|
thumbFile, err = os.Create(path.Join(albumCachePath, thumbnailToken+".jpg"))
|
|
|
|
if err != nil {
|
|
|
|
log.Println("ERROR: Could not make thumbnail file")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer thumbFile.Close()
|
|
|
|
|
|
|
|
jpeg.Encode(thumbFile, thumbnailImage, &jpeg.Options{Quality: 70})
|
|
|
|
|
|
|
|
thumbSize := thumbnailImage.Bounds().Max
|
|
|
|
thumbRes, err := tx.Exec("INSERT INTO photo_url (token, width, height) VALUES (?, ?, ?)", thumbnailToken, thumbSize.X, thumbSize.Y)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
thumbUrlId, err := thumbRes.LastInsertId()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
origSize := image.Bounds().Max
|
|
|
|
origRes, err := tx.Exec("INSERT INTO photo_url (token, width, height) VALUES (?, ?, ?)", originalToken, origSize.X, origSize.Y)
|
2020-02-02 00:29:42 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-02-02 18:18:38 +01:00
|
|
|
origUrlId, err := origRes.LastInsertId()
|
|
|
|
|
|
|
|
_, err = tx.Exec("INSERT INTO photo (title, path, album_id, original_url, thumbnail_url) VALUES (?, ?, ?, ?, ?)", photoName, photoPath, albumId, origUrlId, thumbUrlId)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("ERROR: Could not insert photo into database")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateToken() string {
|
|
|
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
|
|
const length = 24
|
|
|
|
|
|
|
|
b := make([]byte, length)
|
|
|
|
for i := range b {
|
|
|
|
b[i] = charset[rand.Intn(len(charset))]
|
|
|
|
}
|
|
|
|
return string(b)
|
2020-02-02 00:29:42 +01:00
|
|
|
}
|