2023-07-12 14:20:41 -07:00
|
|
|
package uploads
|
2023-04-14 08:28:23 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"image"
|
|
|
|
"os/exec"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
2023-07-13 09:01:28 -07:00
|
|
|
_ "golang.org/x/image/webp"
|
|
|
|
|
2023-04-14 08:28:23 -07:00
|
|
|
"github.com/disintegration/imaging"
|
|
|
|
"github.com/gochan-org/gochan/pkg/config"
|
|
|
|
"github.com/gochan-org/gochan/pkg/gcutil"
|
|
|
|
)
|
|
|
|
|
2023-07-12 10:56:03 -07:00
|
|
|
type ThumbnailCategory int
|
|
|
|
|
|
|
|
const (
|
|
|
|
ThumbnailOP ThumbnailCategory = iota
|
|
|
|
ThumbnailReply
|
|
|
|
ThumbnailCatalog
|
|
|
|
)
|
|
|
|
|
|
|
|
func createImageThumbnail(imageObj image.Image, boardDir string, thumbType ThumbnailCategory) image.Image {
|
2023-04-14 08:28:23 -07:00
|
|
|
thumbWidth, thumbHeight := getBoardThumbnailSize(boardDir, thumbType)
|
|
|
|
|
|
|
|
oldRect := imageObj.Bounds()
|
|
|
|
if thumbWidth >= oldRect.Max.X && thumbHeight >= oldRect.Max.Y {
|
|
|
|
return imageObj
|
|
|
|
}
|
|
|
|
|
|
|
|
thumbW, thumbH := getThumbnailSize(oldRect.Max.X, oldRect.Max.Y, boardDir, thumbType)
|
|
|
|
imageObj = imaging.Resize(imageObj, thumbW, thumbH, imaging.CatmullRom) // resize to 600x400 px using CatmullRom cubic filter
|
|
|
|
return imageObj
|
|
|
|
}
|
|
|
|
|
|
|
|
func createVideoThumbnail(video, thumb string, size int) error {
|
|
|
|
sizeStr := strconv.Itoa(size)
|
2023-04-14 12:17:09 -07:00
|
|
|
outputBytes, err := exec.Command("ffmpeg", "-y" /* "-itsoffset", "-1", */, "-i", video, "-vframes", "1", "-filter:v", "scale='min("+sizeStr+"\\, "+sizeStr+"):-1'", thumb).CombinedOutput()
|
2023-04-14 08:28:23 -07:00
|
|
|
if err != nil {
|
|
|
|
outputStringArr := strings.Split(string(outputBytes), "\n")
|
|
|
|
if len(outputStringArr) > 1 {
|
|
|
|
outputString := outputStringArr[len(outputStringArr)-2]
|
|
|
|
err = errors.New(outputString)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-07-12 10:56:03 -07:00
|
|
|
func getBoardThumbnailSize(boardDir string, thumbType ThumbnailCategory) (int, int) {
|
2023-04-14 08:28:23 -07:00
|
|
|
boardCfg := config.GetBoardConfig(boardDir)
|
|
|
|
switch thumbType {
|
2023-07-12 10:56:03 -07:00
|
|
|
case ThumbnailOP:
|
2023-04-14 08:28:23 -07:00
|
|
|
return boardCfg.ThumbWidth, boardCfg.ThumbHeight
|
2023-07-12 10:56:03 -07:00
|
|
|
case ThumbnailReply:
|
2023-04-14 08:28:23 -07:00
|
|
|
return boardCfg.ThumbWidthReply, boardCfg.ThumbHeightReply
|
2023-07-12 10:56:03 -07:00
|
|
|
case ThumbnailCatalog:
|
2023-04-14 08:28:23 -07:00
|
|
|
return boardCfg.ThumbWidth, boardCfg.ThumbHeight
|
|
|
|
}
|
|
|
|
// todo: use reflect package to print location to error log, because this shouldn't happen
|
|
|
|
return -1, -1
|
|
|
|
}
|
|
|
|
|
|
|
|
// find out what out thumbnail's width and height should be, partially ripped from Kusaba X
|
2023-07-12 10:56:03 -07:00
|
|
|
func getThumbnailSize(uploadWidth, uploadHeight int, boardDir string, thumbType ThumbnailCategory) (newWidth, newHeight int) {
|
2023-04-14 08:28:23 -07:00
|
|
|
thumbWidth, thumbHeight := getBoardThumbnailSize(boardDir, thumbType)
|
|
|
|
if uploadWidth < thumbWidth && uploadHeight < thumbHeight {
|
|
|
|
newWidth = uploadWidth
|
|
|
|
newHeight = uploadHeight
|
|
|
|
} else if uploadWidth == uploadHeight {
|
|
|
|
newWidth = thumbWidth
|
|
|
|
newHeight = thumbHeight
|
|
|
|
} else {
|
|
|
|
var percent float32
|
|
|
|
if uploadWidth > uploadHeight {
|
|
|
|
percent = float32(thumbWidth) / float32(uploadWidth)
|
|
|
|
} else {
|
|
|
|
percent = float32(thumbHeight) / float32(uploadHeight)
|
|
|
|
}
|
|
|
|
newWidth = int(float32(uploadWidth) * percent)
|
|
|
|
newHeight = int(float32(uploadHeight) * percent)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2023-07-12 10:56:03 -07:00
|
|
|
func ShouldCreateThumbnail(imgPath string, imgWidth int, imgHeight int, thumbWidth int, thumbHeight int) bool {
|
2023-04-14 08:28:23 -07:00
|
|
|
ext := strings.ToLower(path.Ext(imgPath))
|
|
|
|
if ext == ".gif" {
|
|
|
|
numFrames, err := numImageFrames(imgPath)
|
|
|
|
if err != nil {
|
|
|
|
gcutil.LogError(err).
|
|
|
|
Str("imgPath", imgPath).Send()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if numFrames > 1 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return imgWidth > thumbWidth || imgHeight > thumbHeight
|
|
|
|
}
|