Work on image processing
This commit is contained in:
parent
d81e945b68
commit
11896a246e
|
@ -1,6 +1,7 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
cache/
|
||||
image-cache/
|
||||
/photos_path
|
||||
|
||||
.env
|
||||
|
|
|
@ -10,6 +10,7 @@ require (
|
|||
github.com/h2non/filetype v1.0.10
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/lib/pq v1.3.0
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/vektah/gqlparser v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
)
|
||||
|
|
|
@ -28,6 +28,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
|
|
|
@ -2,14 +2,110 @@ package scanner
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/nfnt/resize"
|
||||
)
|
||||
|
||||
func ProcessImage(tx *sql.Tx, photoPath string, albumId int) error {
|
||||
|
||||
log.Printf("Processing image: %s\n", photoPath)
|
||||
|
||||
photoName := path.Base(photoPath)
|
||||
|
||||
_, err := tx.Exec("INSERT IGNORE INTO photo (title, path, album_id) VALUES (?, ?, ?)", photoName, photoPath, albumId)
|
||||
if err != nil {
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -79,23 +79,31 @@ func scan(database *sql.DB, user *models.User) {
|
|||
return
|
||||
}
|
||||
|
||||
// Commit album transaction
|
||||
if err := tx.Commit(); err != nil {
|
||||
log.Printf("ERROR: Could not commit database transaction: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Scan for photos
|
||||
for _, item := range dirContent {
|
||||
photoPath := path.Join(albumPath, item.Name())
|
||||
|
||||
if !item.IsDir() && isPathImage(photoPath) {
|
||||
tx, err := database.Begin()
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Could not begin database transaction for image %s: %s\n", photoPath, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ProcessImage(tx, photoPath, albumId); err != nil {
|
||||
fmt.Printf("ERROR: Could not proccess image %s: %s", photoPath, err)
|
||||
log.Printf("ERROR: processing image %s: %s", photoPath, err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Commit album and photos transaction
|
||||
if err := tx.Commit(); err != nil {
|
||||
log.Printf("ERROR: Could not commit database transaction: %s\n", err)
|
||||
return
|
||||
tx.Commit()
|
||||
}
|
||||
}
|
||||
|
||||
// Scan for sub-albums
|
||||
|
@ -148,8 +156,8 @@ func directoryContainsPhotos(rootPath string) bool {
|
|||
var supported_mimetypes = [...]string{
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/tiff",
|
||||
"image/x-canon-cr2",
|
||||
// "image/tiff",
|
||||
// "image/x-canon-cr2",
|
||||
"image/bmp",
|
||||
}
|
||||
|
||||
|
@ -159,6 +167,7 @@ func isPathImage(path string) bool {
|
|||
log.Printf("Could not open file %s: %s\n", path, err)
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
head := make([]byte, 261)
|
||||
if _, err := file.Read(head); err != nil {
|
||||
|
|
Loading…
Reference in New Issue