On the fly image conversion

This commit is contained in:
2021-02-21 12:31:03 -05:00
parent 5212d7bf70
commit 901a69bb91
13 changed files with 296 additions and 53 deletions

View File

@@ -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
}

View File

@@ -1 +0,0 @@
package api