On the fly image conversion
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/davidbyttow/govips/v2/vips"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
@@ -23,21 +30,14 @@ func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Acquire Width & Height Parameters
|
||||
query := r.URL.Query()
|
||||
width := query["width"]
|
||||
height := query["height"]
|
||||
_ = width
|
||||
_ = height
|
||||
|
||||
// TODO: Caching & Resizing
|
||||
// - If both, force resize with new scale
|
||||
// - If one, scale resize proportionally
|
||||
width, _ := strconv.Atoi(r.URL.Query().Get("width"))
|
||||
|
||||
// Pull out userID
|
||||
authContext := r.Context().Value("auth").(*model.AuthContext)
|
||||
rawUserID, _ := (*authContext.AccessToken).Get("sub")
|
||||
userID := rawUserID.(string)
|
||||
|
||||
// TODO: Derive Cache & Width Location
|
||||
// Derive Path
|
||||
fileName := path.Base(r.URL.Path)
|
||||
folderPath := path.Join("/" + api.Config.DataPath + "/media/" + userID)
|
||||
@@ -46,10 +46,54 @@ func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if File Exists
|
||||
_, err := os.Stat(mediaPath)
|
||||
if os.IsNotExist(err) {
|
||||
// TODO: Different HTTP Response Code?
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
log.Warn("[media] Image does not exist on disk")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, mediaPath)
|
||||
mediaFile, err := resizeAndConvertImage(mediaPath, width)
|
||||
if err != nil {
|
||||
log.Warn("[media] Image conversion failed:", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Cache mediaFile
|
||||
|
||||
http.ServeContent(w, r, fileName, time.Time{}, bytes.NewReader(mediaFile))
|
||||
}
|
||||
|
||||
func resizeAndConvertImage(path string, desiredWidth int) ([]byte, error) {
|
||||
inputImage, err := vips.NewImageFromFile(path)
|
||||
if err != nil {
|
||||
return nil, errors.New("[media] Unable to read image")
|
||||
}
|
||||
|
||||
// If we're viewing full image, we want full quality
|
||||
desiredQuality := 100
|
||||
|
||||
// Do we need to scale?
|
||||
if desiredWidth != 0 && inputImage.Width() > desiredWidth {
|
||||
desiredQuality = 50
|
||||
desiredScale := float64(desiredWidth) / float64(inputImage.Width())
|
||||
err := inputImage.Resize(desiredScale, vips.KernelLanczos3)
|
||||
if err != nil {
|
||||
return nil, errors.New("[media] Unable to resize")
|
||||
}
|
||||
} else if inputImage.Format() == vips.ImageTypeJPEG {
|
||||
// Return raw file
|
||||
return ioutil.ReadFile(path)
|
||||
}
|
||||
|
||||
// Return non-converted but scaled image
|
||||
if inputImage.Format() == vips.ImageTypeJPEG {
|
||||
imageBytes, _, err := inputImage.ExportNative()
|
||||
return imageBytes, err
|
||||
}
|
||||
|
||||
// Convert
|
||||
ep := vips.NewJpegExportParams()
|
||||
ep.Quality = desiredQuality
|
||||
imageBytes, _, err := inputImage.ExportJpeg(ep)
|
||||
return imageBytes, err
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package api
|
||||
Reference in New Issue
Block a user