From 2042c7520d58bc6bd83e31d5eb5ceab080c7a2c7 Mon Sep 17 00:00:00 2001 From: Justin Hawkins Date: Sun, 7 Nov 2021 13:25:18 +1030 Subject: [PATCH] Add image thumbnail previews to the uploads page. --- imageprocess/imageprocess.go | 4 +++ imageprocess/thumb.go | 47 ++++++++++++++++++++++++ upload/upload.go | 9 +++++ web/data/uploads.html | 7 +++- web/server.go | 70 +++++++++++++++++++++++++----------- 5 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 imageprocess/imageprocess.go create mode 100644 imageprocess/thumb.go diff --git a/imageprocess/imageprocess.go b/imageprocess/imageprocess.go new file mode 100644 index 0000000..5e63321 --- /dev/null +++ b/imageprocess/imageprocess.go @@ -0,0 +1,4 @@ +package imageprocess + +type Processor struct { +} diff --git a/imageprocess/thumb.go b/imageprocess/thumb.go new file mode 100644 index 0000000..58fba9d --- /dev/null +++ b/imageprocess/thumb.go @@ -0,0 +1,47 @@ +package imageprocess + +import ( + "fmt" + "image" + "image/png" + "io" + "os" + + "github.com/tardisx/discord-auto-upload/upload" + "golang.org/x/image/draw" +) + +const ( + thumbnailMaxX = 128 + thumbnailMaxY = 128 +) + +func (ip *Processor) ThumbPNG(ul *upload.Upload, w io.Writer) error { + file, err := os.Open(ul.OriginalFilename) + if err != nil { + return fmt.Errorf("could not open file: %s", err) + } + defer file.Close() + im, _, err := image.Decode(file) + if err != nil { + return fmt.Errorf("could not decode file: %s", err) + } + + newXY := image.Point{} + // test width + if im.Bounds().Max.X/thumbnailMaxX > im.Bounds().Max.Y/thumbnailMaxY { + newXY.X = thumbnailMaxX + newXY.Y = im.Bounds().Max.Y / (im.Bounds().Max.X / thumbnailMaxX) + } else { + newXY.Y = thumbnailMaxY + newXY.X = im.Bounds().Max.X / (im.Bounds().Max.Y / thumbnailMaxY) + } + + dst := image.NewRGBA(image.Rect(0, 0, newXY.X, newXY.Y)) + draw.BiLinear.Scale(dst, dst.Rect, im, im.Bounds(), draw.Over, nil) + + png.Encode(w, dst) + + return nil + +} diff --git a/upload/upload.go b/upload/upload.go index 2c6114e..d8482bf 100644 --- a/upload/upload.go +++ b/upload/upload.go @@ -98,6 +98,15 @@ func (u *Uploader) Upload() { } } +func (u *Uploader) UploadById(id int32) *Upload { + for _, anUpload := range u.Uploads { + if anUpload.Id == int32(id) { + return anUpload + } + } + return nil +} + func (u *Upload) processUpload() error { daulog.SendLog(fmt.Sprintf("Uploading: %s", u.OriginalFilename), daulog.LogTypeInfo) diff --git a/web/data/uploads.html b/web/data/uploads.html index 6ee3a83..2458fac 100644 --- a/web/data/uploads.html +++ b/web/data/uploads.html @@ -11,6 +11,7 @@ filename actions +   @@ -20,8 +21,8 @@ - + @@ -35,6 +36,7 @@ filename actions +   @@ -45,6 +47,7 @@ + @@ -58,6 +61,7 @@ filename state +   @@ -66,6 +70,7 @@ + diff --git a/web/server.go b/web/server.go index 0aa29ad..5234f03 100644 --- a/web/server.go +++ b/web/server.go @@ -16,6 +16,7 @@ import ( "github.com/gorilla/mux" "github.com/tardisx/discord-auto-upload/config" + "github.com/tardisx/discord-auto-upload/imageprocess" daulog "github.com/tardisx/discord-auto-upload/log" "github.com/tardisx/discord-auto-upload/upload" "github.com/tardisx/discord-auto-upload/version" @@ -168,6 +169,30 @@ func (ws *WebService) getUploads(w http.ResponseWriter, r *http.Request) { w.Write([]byte(text)) } +func (ws *WebService) imageThumb(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Content-Type", "image/png") + processor := imageprocess.Processor{} + + vars := mux.Vars(r) + id, err := strconv.ParseInt(vars["id"], 10, 32) + if err != nil { + returnJSONError(w, "bad id") + return + } + + ul := ws.Uploader.UploadById(int32(id)) + if ul == nil { + returnJSONError(w, "bad id") + return + } + err = processor.ThumbPNG(ul, w) + if err != nil { + returnJSONError(w, "could not create thumb") + return + } +} + func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -182,26 +207,28 @@ func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) { return } - for _, anUpload := range ws.Uploader.Uploads { - if anUpload.Id == int32(id) { - if anUpload.State == upload.StatePending { - if change == "start" { - anUpload.State = upload.StateQueued - res := StartUploadResponse{Success: true, Message: "upload queued"} - resString, _ := json.Marshal(res) - w.Write(resString) - return - } else if change == "skip" { - anUpload.State = upload.StateSkipped - res := StartUploadResponse{Success: true, Message: "upload skipped"} - resString, _ := json.Marshal(res) - w.Write(resString) - return - } else { - returnJSONError(w, "bad change type") - return - } - } + anUpload := ws.Uploader.UploadById(int32(id)) + if anUpload == nil { + returnJSONError(w, "bad id") + return + } + + if anUpload.State == upload.StatePending { + if change == "start" { + anUpload.State = upload.StateQueued + res := StartUploadResponse{Success: true, Message: "upload queued"} + resString, _ := json.Marshal(res) + w.Write(resString) + return + } else if change == "skip" { + anUpload.State = upload.StateSkipped + res := StartUploadResponse{Success: true, Message: "upload skipped"} + resString, _ := json.Marshal(res) + w.Write(resString) + return + } else { + returnJSONError(w, "bad change type") + return } } res := StartUploadResponse{Success: false, Message: "upload does not exist, or already queued"} @@ -211,7 +238,6 @@ func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) { return } returnJSONError(w, "bad request") - return } @@ -223,6 +249,8 @@ func (ws *WebService) StartWebServer() { r.HandleFunc("/rest/uploads", ws.getUploads) r.HandleFunc("/rest/upload/{id:[0-9]+}/{change}", ws.modifyUpload) + r.HandleFunc("/rest/image/{id:[0-9]+}/thumb", ws.imageThumb) + r.HandleFunc("/rest/config", ws.handleConfig) r.PathPrefix("/").HandlerFunc(ws.getStatic)