mirror of
https://github.com/woodchen-ink/webp_server_go.git
synced 2025-07-18 05:32:02 +08:00
* WIP JXL * Fix test * Tries to fix autobuild * Tries to fix autobuild * Add setup go in codeql * Bump actions version * Do not print curl output in CI * Do not print curl output in CI * Remove Metadata on RAW image * Update sample config * better loop * Prefetch should also respect AllowedType * Better Export params and UA handle * Only do conversion on supported formats * CONVERT_TYPES default to webp only * CONVERT_TYPES default to webp only * Add GIF to AllowedTypes * Update README
149 lines
4.2 KiB
Go
149 lines
4.2 KiB
Go
package encoder
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path"
|
|
"slices"
|
|
"webp_server_go/config"
|
|
|
|
"github.com/davidbyttow/govips/v2/vips"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func resizeImage(img *vips.ImageRef, extraParams config.ExtraParams) error {
|
|
imageHeight := img.Height()
|
|
imageWidth := img.Width()
|
|
|
|
imgHeightWidthRatio := float32(imageHeight) / float32(imageWidth)
|
|
|
|
// Here we have width, height and max_width, max_height
|
|
// Both pairs cannot be used at the same time
|
|
|
|
// max_height and max_width are used to make sure bigger images are resized to max_height and max_width
|
|
// e.g, 500x500px image with max_width=200,max_height=100 will be resized to 100x100
|
|
// while smaller images are untouched
|
|
|
|
// If both are used, we will use width and height
|
|
|
|
if extraParams.MaxHeight > 0 && extraParams.MaxWidth > 0 {
|
|
// If any of it exceeds
|
|
if imageHeight > extraParams.MaxHeight || imageWidth > extraParams.MaxWidth {
|
|
// Check which dimension exceeds most
|
|
heightExceedRatio := float32(imageHeight) / float32(extraParams.MaxHeight)
|
|
widthExceedRatio := float32(imageWidth) / float32(extraParams.MaxWidth)
|
|
// If height exceeds more, like 500x500 -> 200x100 (2.5 < 5)
|
|
// Take max_height as new height ,resize and retain ratio
|
|
if heightExceedRatio > widthExceedRatio {
|
|
err := img.Thumbnail(int(float32(extraParams.MaxHeight)/imgHeightWidthRatio), extraParams.MaxHeight, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
err := img.Thumbnail(extraParams.MaxWidth, int(float32(extraParams.MaxWidth)*imgHeightWidthRatio), 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if extraParams.MaxHeight > 0 && imageHeight > extraParams.MaxHeight && extraParams.MaxWidth == 0 {
|
|
err := img.Thumbnail(int(float32(extraParams.MaxHeight)/imgHeightWidthRatio), extraParams.MaxHeight, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if extraParams.MaxWidth > 0 && imageWidth > extraParams.MaxWidth && extraParams.MaxHeight == 0 {
|
|
err := img.Thumbnail(extraParams.MaxWidth, int(float32(extraParams.MaxWidth)*imgHeightWidthRatio), 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if extraParams.Width > 0 && extraParams.Height > 0 {
|
|
err := img.Thumbnail(extraParams.Width, extraParams.Height, vips.InterestingAttention)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if extraParams.Width > 0 && extraParams.Height == 0 {
|
|
err := img.Thumbnail(extraParams.Width, int(float32(extraParams.Width)*imgHeightWidthRatio), 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if extraParams.Height > 0 && extraParams.Width == 0 {
|
|
err := img.Thumbnail(int(float32(extraParams.Height)/imgHeightWidthRatio), extraParams.Height, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ResizeItself(raw, dest string, extraParams config.ExtraParams) {
|
|
log.Infof("Resize %s itself to %s", raw, dest)
|
|
|
|
// we need to create dir first
|
|
var err = os.MkdirAll(path.Dir(dest), 0755)
|
|
if err != nil {
|
|
log.Error(err.Error())
|
|
}
|
|
|
|
img, err := vips.LoadImageFromFile(raw, &vips.ImportParams{
|
|
FailOnError: boolFalse,
|
|
})
|
|
if err != nil {
|
|
log.Warnf("Could not load %s: %s", raw, err)
|
|
return
|
|
}
|
|
_ = resizeImage(img, extraParams)
|
|
if config.Config.StripMetadata {
|
|
img.RemoveMetadata()
|
|
}
|
|
buf, _, _ := img.ExportNative()
|
|
_ = os.WriteFile(dest, buf, 0600)
|
|
img.Close()
|
|
}
|
|
|
|
// Pre-process image(auto rotate, resize, etc.)
|
|
func preProcessImage(img *vips.ImageRef, imageType string, extraParams config.ExtraParams) error {
|
|
// Check Width/Height and ignore image formats
|
|
switch imageType {
|
|
case "webp":
|
|
if img.Metadata().Width > config.WebpMax || img.Metadata().Height > config.WebpMax {
|
|
return errors.New("WebP: image too large")
|
|
}
|
|
imageFormat := img.Format()
|
|
if slices.Contains(webpIgnore, imageFormat) {
|
|
// Return err to render original image
|
|
return errors.New("WebP encoder: ignore image type")
|
|
}
|
|
case "avif":
|
|
if img.Metadata().Width > config.AvifMax || img.Metadata().Height > config.AvifMax {
|
|
return errors.New("AVIF: image too large")
|
|
}
|
|
imageFormat := img.Format()
|
|
if slices.Contains(avifIgnore, imageFormat) {
|
|
// Return err to render original image
|
|
return errors.New("AVIF encoder: ignore image type")
|
|
}
|
|
}
|
|
|
|
// Auto rotate
|
|
err := img.AutoRotate()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if config.Config.EnableExtraParams {
|
|
err = resizeImage(img, extraParams)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|