214 lines
5.6 KiB
Go
214 lines
5.6 KiB
Go
package rest
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/disintegration/imaging"
|
|
"github.com/eyebluecn/tank/code/core"
|
|
"github.com/eyebluecn/tank/code/tool/result"
|
|
"github.com/eyebluecn/tank/code/tool/util"
|
|
"image"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
//@Service
|
|
type ImageCacheService struct {
|
|
BaseBean
|
|
imageCacheDao *ImageCacheDao
|
|
userDao *UserDao
|
|
matterDao *MatterDao
|
|
}
|
|
|
|
func (this *ImageCacheService) Init() {
|
|
this.BaseBean.Init()
|
|
|
|
b := core.CONTEXT.GetBean(this.imageCacheDao)
|
|
if b, ok := b.(*ImageCacheDao); ok {
|
|
this.imageCacheDao = b
|
|
}
|
|
|
|
b = core.CONTEXT.GetBean(this.userDao)
|
|
if b, ok := b.(*UserDao); ok {
|
|
this.userDao = b
|
|
}
|
|
|
|
b = core.CONTEXT.GetBean(this.matterDao)
|
|
if b, ok := b.(*MatterDao); ok {
|
|
this.matterDao = b
|
|
}
|
|
|
|
}
|
|
|
|
func (this *ImageCacheService) Detail(uuid string) *ImageCache {
|
|
|
|
imageCache := this.imageCacheDao.CheckByUuid(uuid)
|
|
|
|
return imageCache
|
|
}
|
|
|
|
// prepare the resize parameters.
|
|
func (this *ImageCacheService) ResizeParams(request *http.Request) (needProcess bool, resizeMode string, resizeWidth int, resizeHeight int) {
|
|
var err error
|
|
|
|
if request.FormValue("ir") != "" {
|
|
//mode_w_h if w or h equal means not required.
|
|
imageResizeStr := request.FormValue("ir")
|
|
arr := strings.Split(imageResizeStr, "_")
|
|
if len(arr) != 3 {
|
|
panic(result.BadRequest("param error. the format is mode_w_h"))
|
|
}
|
|
|
|
imageResizeM := arr[0]
|
|
if imageResizeM == "" {
|
|
imageResizeM = "fit"
|
|
} else if imageResizeM != "fit" && imageResizeM != "fill" && imageResizeM != "fixed" {
|
|
panic(result.BadRequest("mode can only be fit/fill/fixed"))
|
|
}
|
|
imageResizeWStr := arr[1]
|
|
var imageResizeW int
|
|
if imageResizeWStr != "" {
|
|
imageResizeW, err = strconv.Atoi(imageResizeWStr)
|
|
this.PanicError(err)
|
|
if imageResizeW < 0 || imageResizeW > 4096 {
|
|
panic(result.BadRequest("zoom size cannot exceed 4096"))
|
|
}
|
|
}
|
|
imageResizeHStr := arr[2]
|
|
var imageResizeH int
|
|
if imageResizeHStr != "" {
|
|
imageResizeH, err = strconv.Atoi(imageResizeHStr)
|
|
this.PanicError(err)
|
|
if imageResizeH < 0 || imageResizeH > 4096 {
|
|
panic(result.BadRequest("zoom size cannot exceed 4096"))
|
|
}
|
|
}
|
|
return true, imageResizeM, imageResizeW, imageResizeH
|
|
} else {
|
|
return false, "", 0, 0
|
|
}
|
|
|
|
}
|
|
|
|
//resize image.
|
|
func (this *ImageCacheService) ResizeImage(request *http.Request, filePath string) *image.NRGBA {
|
|
|
|
diskFile, err := os.Open(filePath)
|
|
this.PanicError(err)
|
|
defer func() {
|
|
e := diskFile.Close()
|
|
this.PanicError(e)
|
|
}()
|
|
|
|
_, imageResizeM, imageResizeW, imageResizeH := this.ResizeParams(request)
|
|
|
|
if imageResizeM == "fit" {
|
|
//fit mode.
|
|
if imageResizeW != 0 {
|
|
//eg. width = 100 height auto in proportion
|
|
|
|
src, err := imaging.Decode(diskFile)
|
|
this.PanicError(err)
|
|
return imaging.Resize(src, imageResizeW, 0, imaging.Lanczos)
|
|
|
|
} else if imageResizeH != 0 {
|
|
//eg. height = 100 width auto in proportion
|
|
|
|
src, err := imaging.Decode(diskFile)
|
|
this.PanicError(err)
|
|
return imaging.Resize(src, 0, imageResizeH, imaging.Lanczos)
|
|
|
|
} else {
|
|
panic(result.BadRequest("mode fit required width or height"))
|
|
}
|
|
} else if imageResizeM == "fill" {
|
|
//fill mode. specify the width and height
|
|
if imageResizeW > 0 && imageResizeH > 0 {
|
|
src, err := imaging.Decode(diskFile)
|
|
this.PanicError(err)
|
|
return imaging.Fill(src, imageResizeW, imageResizeH, imaging.Center, imaging.Lanczos)
|
|
|
|
} else {
|
|
panic(result.BadRequest("mode fill required width and height"))
|
|
}
|
|
} else if imageResizeM == "fixed" {
|
|
//fixed mode
|
|
if imageResizeW > 0 && imageResizeH > 0 {
|
|
src, err := imaging.Decode(diskFile)
|
|
this.PanicError(err)
|
|
return imaging.Resize(src, imageResizeW, imageResizeH, imaging.Lanczos)
|
|
|
|
} else {
|
|
panic(result.BadRequest("mode fixed required width and height"))
|
|
}
|
|
} else {
|
|
panic(result.BadRequest("not support mode %s", imageResizeM))
|
|
}
|
|
}
|
|
|
|
//cache an image
|
|
func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *http.Request, matter *Matter) *ImageCache {
|
|
|
|
//only these image can do.
|
|
extension := util.GetExtension(matter.Name)
|
|
formats := map[string]imaging.Format{
|
|
".jpg": imaging.JPEG,
|
|
".jpeg": imaging.JPEG,
|
|
".png": imaging.PNG,
|
|
".tif": imaging.TIFF,
|
|
".tiff": imaging.TIFF,
|
|
".bmp": imaging.BMP,
|
|
".gif": imaging.GIF,
|
|
}
|
|
|
|
_, imageResizeM, imageResizeW, imageResizeH := this.ResizeParams(request)
|
|
mode := fmt.Sprintf("%s_%d_%d", imageResizeM, imageResizeW, imageResizeH)
|
|
|
|
format, ok := formats[extension]
|
|
if !ok {
|
|
panic(result.BadRequest("not support this kind of image's (%s) resize", extension))
|
|
}
|
|
|
|
user := this.userDao.FindByUuid(matter.UserUuid)
|
|
|
|
dstImage := this.ResizeImage(request, matter.AbsolutePath())
|
|
|
|
cacheImageName := util.GetSimpleFileName(matter.Name) + "_" + mode + extension
|
|
cacheImageRelativePath := util.GetSimpleFileName(matter.Path) + "_" + mode + extension
|
|
cacheImageAbsolutePath := GetUserCacheRootDir(user.Username) + util.GetSimpleFileName(matter.Path) + "_" + mode + extension
|
|
|
|
//create directory
|
|
dir := filepath.Dir(cacheImageAbsolutePath)
|
|
util.MakeDirAll(dir)
|
|
|
|
fileWriter, err := os.Create(cacheImageAbsolutePath)
|
|
this.PanicError(err)
|
|
defer func() {
|
|
e := fileWriter.Close()
|
|
this.PanicError(e)
|
|
}()
|
|
|
|
//store on disk after handle
|
|
err = imaging.Encode(fileWriter, dstImage, format)
|
|
this.PanicError(err)
|
|
|
|
fileInfo, err := fileWriter.Stat()
|
|
this.PanicError(err)
|
|
|
|
imageCache := &ImageCache{
|
|
Name: cacheImageName,
|
|
UserUuid: matter.UserUuid,
|
|
Username: user.Username,
|
|
MatterUuid: matter.Uuid,
|
|
MatterName: matter.Name,
|
|
Mode: mode,
|
|
Size: fileInfo.Size(),
|
|
Path: cacheImageRelativePath,
|
|
}
|
|
this.imageCacheDao.Create(imageCache)
|
|
|
|
return imageCache
|
|
}
|