feat: generate a BlurHash when uploading a new image
This commit is contained in:
parent
362706b38d
commit
f83b09af59
5 changed files with 47 additions and 17 deletions
|
@ -640,7 +640,7 @@ func UpdateList(s *xorm.Session, list *List, auth web.Auth, updateListBackground
|
|||
}
|
||||
|
||||
if updateListBackground {
|
||||
colsToUpdate = append(colsToUpdate, "background_file_id")
|
||||
colsToUpdate = append(colsToUpdate, "background_file_id", "background_blur_hash")
|
||||
}
|
||||
|
||||
wasFavorite, err := isFavorite(s, list.ID, auth, FavoriteKindList)
|
||||
|
@ -801,14 +801,15 @@ func (l *List) Delete(s *xorm.Session, a web.Auth) (err error) {
|
|||
}
|
||||
|
||||
// SetListBackground sets a background file as list background in the db
|
||||
func SetListBackground(s *xorm.Session, listID int64, background *files.File) (err error) {
|
||||
func SetListBackground(s *xorm.Session, listID int64, background *files.File, blurHash string) (err error) {
|
||||
l := &List{
|
||||
ID: listID,
|
||||
BackgroundFileID: background.ID,
|
||||
ID: listID,
|
||||
BackgroundFileID: background.ID,
|
||||
BackgroundBlurHash: blurHash,
|
||||
}
|
||||
_, err = s.
|
||||
Where("id = ?", l.ID).
|
||||
Cols("background_file_id").
|
||||
Cols("background_file_id", "background_blur_hash").
|
||||
Update(l)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, doer web.Auth) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if err := SetListBackground(s, ld.List.ID, file); err != nil {
|
||||
if err := SetListBackground(s, ld.List.ID, file, ld.List.BackgroundBlurHash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"github.com/bbrks/go-blurhash"
|
||||
"golang.org/x/image/draw"
|
||||
"image"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -134,6 +137,18 @@ func (bp *BackgroundProvider) SetBackground(c echo.Context) error {
|
|||
return c.JSON(http.StatusOK, list)
|
||||
}
|
||||
|
||||
func CreateBlurHash(srcf io.Reader) (hash string, err error) {
|
||||
src, _, err := image.Decode(srcf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dst := image.NewRGBA(image.Rect(0, 0, 32, 32))
|
||||
draw.NearestNeighbor.Scale(dst, dst.Rect, src, src.Bounds(), draw.Over, nil)
|
||||
|
||||
return blurhash.Encode(4, 3, dst)
|
||||
}
|
||||
|
||||
// UploadBackground uploads a background and passes the id of the uploaded file as an Image to the Set function of the BackgroundProvider.
|
||||
func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
||||
s := db.NewSession()
|
||||
|
@ -153,15 +168,15 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
src, err := file.Open()
|
||||
srcf, err := file.Open()
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
defer srcf.Close()
|
||||
|
||||
// Validate we're dealing with an image
|
||||
mime, err := mimetype.DetectReader(src)
|
||||
mime, err := mimetype.DetectReader(srcf)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
|
@ -170,10 +185,10 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
_ = s.Rollback()
|
||||
return c.JSON(http.StatusBadRequest, models.Message{Message: "Uploaded file is no image."})
|
||||
}
|
||||
_, _ = src.Seek(0, io.SeekStart)
|
||||
_, _ = srcf.Seek(0, io.SeekStart)
|
||||
|
||||
// Save the file
|
||||
f, err := files.CreateWithMime(src, file.Filename, uint64(file.Size), auth, mime.String())
|
||||
f, err := files.CreateWithMime(srcf, file.Filename, uint64(file.Size), auth, mime.String())
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
if files.IsErrFileIsTooLarge(err) {
|
||||
|
@ -183,9 +198,16 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
image := &background.Image{ID: strconv.FormatInt(f.ID, 10)}
|
||||
// Generate a blurHash
|
||||
_, _ = srcf.Seek(0, io.SeekStart)
|
||||
list.BackgroundBlurHash, err = CreateBlurHash(srcf)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
err = p.Set(s, image, list, auth)
|
||||
// Save it
|
||||
img := &background.Image{ID: strconv.FormatInt(f.ID, 10)}
|
||||
err = p.Set(s, img, list, auth)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
|
@ -300,6 +322,7 @@ func RemoveListBackground(c echo.Context) error {
|
|||
|
||||
list.BackgroundFileID = 0
|
||||
list.BackgroundInformation = nil
|
||||
list.BackgroundBlurHash = ""
|
||||
err = models.UpdateList(s, list, auth, true)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -52,7 +52,7 @@ func (p *Provider) Search(s *xorm.Session, search string, page int64) (result []
|
|||
// @Failure 404 {object} models.Message "The list does not exist."
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /lists/{id}/backgrounds/upload [put]
|
||||
func (p *Provider) Set(s *xorm.Session, image *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
func (p *Provider) Set(s *xorm.Session, img *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
// Remove the old background if one exists
|
||||
if list.BackgroundFileID != 0 {
|
||||
file := files.File{ID: list.BackgroundFileID}
|
||||
|
@ -62,12 +62,12 @@ func (p *Provider) Set(s *xorm.Session, image *background.Image, list *models.Li
|
|||
}
|
||||
|
||||
file := &files.File{}
|
||||
file.ID, err = strconv.ParseInt(image.ID, 10, 64)
|
||||
file.ID, err = strconv.ParseInt(img.ID, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
list.BackgroundInformation = &models.ListBackgroundType{Type: models.ListBackgroundUpload}
|
||||
|
||||
return models.SetListBackground(s, list.ID, file)
|
||||
return models.SetListBackground(s, list.ID, file, list.BackgroundBlurHash)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package migration
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"code.vikunja.io/api/pkg/modules/background/handler"
|
||||
"io/ioutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
|
@ -115,7 +116,12 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
|||
return err
|
||||
}
|
||||
|
||||
err = models.SetListBackground(s, l.ID, file)
|
||||
hash, err := handler.CreateBlurHash(backgroundFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = models.SetListBackground(s, l.ID, file, hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue