tavern/web/handler_image.go

141 lines
3.5 KiB
Go

package web
import (
"encoding/hex"
"fmt"
"image"
"image/jpeg"
"image/png"
"net/http"
"github.com/buckket/go-blurhash"
"github.com/gin-gonic/gin"
"github.com/nfnt/resize"
"github.com/ngerakines/tavern/errors"
"github.com/ngerakines/tavern/storage"
)
func (h handler) viewAsset(c *gin.Context) {
checksum := c.Param("checksum")
img, err := h.storage.GetImageByChecksum(c.Request.Context(), checksum)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, nil)
return
}
h.internalServerErrorJSON(c, err)
return
}
readerCloser, err := h.assetStorage.Read(c.Request.Context(), img.Location)
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
var contentType = "application/octet-stream"
// TODO: Handle other content types.
switch img.ContentType {
case storage.ContentTypeJPG:
contentType = "image/jpeg"
case storage.ContentTypePNG:
contentType = "image/png"
}
extraHeaders := map[string]string{
"Cache-Control": "max-age=7200",
}
c.DataFromReader(http.StatusOK, int64(img.Size), contentType, readerCloser, extraHeaders)
}
func (h handler) viewThumbnail(c *gin.Context) {
checksum := c.Param("checksum")
img, err := h.storage.GetImageByChecksum(c.Request.Context(), checksum)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, nil)
return
}
h.internalServerErrorJSON(c, err)
return
}
readerCloser, err := h.assetStorage.Read(c.Request.Context(), img.Location)
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
// TODO: Log this error
defer readerCloser.Close()
readImage, _, err := image.Decode(readerCloser)
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
m := resize.Thumbnail(40, 40, readImage, resize.NearestNeighbor)
// TODO: Handle other content types.
switch img.ContentType {
case storage.ContentTypeJPG:
c.Writer.Header().Add("Cache-Control", "max-age=7200")
c.Writer.Header().Add("Content-Type", "image/jpeg")
// TODO: handle this error.
jpeg.Encode(c.Writer, m, nil)
case storage.ContentTypePNG:
c.Writer.Header().Add("Cache-Control", "max-age=7200")
c.Writer.Header().Add("Content-Type", "image/png")
// TODO: handle this error.
png.Encode(c.Writer, m)
default:
h.internalServerErrorJSON(c, fmt.Errorf("unable to process image thumbnail"))
}
}
func (h handler) viewBlur(c *gin.Context) {
encBlurHash := c.Param("blurHash")
blurHash, err := hex.DecodeString(encBlurHash)
if err != nil {
h.badRequestJSON(c, err)
return
}
height := intParam(c, "height", 60)
width := intParam(c, "width", 60)
blurImg, err := blurhash.Decode(string(blurHash), width, height, 1)
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
c.Writer.Header().Add("Cache-Control", "max-age=7200")
c.Writer.Header().Add("Content-Type", "image/png")
// Todo: handle this error
png.Encode(c.Writer, blurImg)
}
func (h handler) viewThumbnailBlur(c *gin.Context) {
checksum := c.Param("checksum")
img, err := h.storage.GetImageByChecksum(c.Request.Context(), checksum)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, err)
return
}
h.internalServerErrorJSON(c, err)
return
}
blurImg, err := blurhash.Decode(img.Blur, 40, 40, 1)
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
c.Writer.Header().Add("Cache-Control", "max-age=7200")
c.Writer.Header().Add("Content-Type", "image/png")
// Todo: handle this error
png.Encode(c.Writer, blurImg)
}