1
0
mirror of https://github.com/coalaura/ffwebp.git synced 2025-09-08 05:49:54 +00:00
This commit is contained in:
2025-08-11 21:17:25 +02:00
parent 06bf222988
commit 738a9f42aa
19 changed files with 442 additions and 12 deletions

View File

@@ -0,0 +1,16 @@
//go:build effects || core || full
// +build effects core full
package builtins
import (
_ "github.com/coalaura/ffwebp/internal/effects/blur"
_ "github.com/coalaura/ffwebp/internal/effects/brightness"
_ "github.com/coalaura/ffwebp/internal/effects/contrast"
_ "github.com/coalaura/ffwebp/internal/effects/grayscale"
_ "github.com/coalaura/ffwebp/internal/effects/hue"
_ "github.com/coalaura/ffwebp/internal/effects/invert"
_ "github.com/coalaura/ffwebp/internal/effects/saturation"
_ "github.com/coalaura/ffwebp/internal/effects/sepia"
_ "github.com/coalaura/ffwebp/internal/effects/sharpen"
)

View File

@@ -42,7 +42,7 @@ func (impl) Flags(flags []cli.Flag) []cli.Flag {
return append(flags,
&cli.IntFlag{
Name: "avif.quality-alpha",
Usage: "AVIF: alpha channel quality in range [0-100]",
Usage: "AVIF: alpha channel quality (0-100)",
Value: 60,
Destination: &qualityA,
Validator: func(v int) error {
@@ -55,7 +55,7 @@ func (impl) Flags(flags []cli.Flag) []cli.Flag {
},
&cli.IntFlag{
Name: "avif.speed",
Usage: "AVIF: encoding speed in range [0-10] (0=slowest/best)",
Usage: "AVIF: encoding speed (0=slowest/best, 10=fastest/worst)",
Value: 6,
Destination: &speed,
Validator: func(v int) error {

View File

@@ -41,7 +41,7 @@ func (impl) Flags(flags []cli.Flag) []cli.Flag {
Destination: &numColors,
Validator: func(value int) error {
if value < 1 || value > 256 {
return fmt.Errorf("invalid number of colors: %d", value)
return fmt.Errorf("invalid gif.colors: %d", value)
}
return nil

View File

@@ -43,7 +43,7 @@ func (impl) Flags(flags []cli.Flag) []cli.Flag {
Destination: &compression,
Validator: func(value int) error {
if value < 0 || value > 3 {
return fmt.Errorf("invalid compression level: %d", value)
return fmt.Errorf("invalid png.compression: %d", value)
}
return nil

View File

@@ -46,7 +46,7 @@ func (impl) Flags(flags []cli.Flag) []cli.Flag {
Destination: &compression,
Validator: func(value int) error {
if value < 0 || value > 4 {
return fmt.Errorf("invalid compression: %d", value)
return fmt.Errorf("invalid tiff.compression: %d", value)
}
return nil

View File

@@ -0,0 +1,38 @@
package blur
import (
"fmt"
"image"
"strconv"
"github.com/anthonynsimon/bild/blur"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "blur"
}
func (impl) Apply(img image.Image, args string) (image.Image, error) {
var radius float64 = 3
if args != "" {
f64, err := strconv.ParseFloat(args, 64)
if err != nil || f64 <= 0 {
return nil, fmt.Errorf("invalid blur radius: %s", args)
}
radius = f64
}
logx.Printf(" applying blur (radius=%.f)\n", radius)
return blur.Gaussian(img, radius), nil
}

View File

@@ -0,0 +1,38 @@
package brightness
import (
"fmt"
"image"
"strconv"
"github.com/anthonynsimon/bild/adjust"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "brightness"
}
func (impl) Apply(img image.Image, args string) (image.Image, error) {
var change float64 = 0.1
if args != "" {
f64, err := strconv.ParseFloat(args, 64)
if err != nil || f64 < -1 || f64 > 1 || f64 == 0 {
return nil, fmt.Errorf("invalid brightness change: %s", args)
}
change = f64
}
logx.Printf(" applying brightness (change=%.f)\n", change)
return adjust.Brightness(img, change), nil
}

View File

@@ -0,0 +1,38 @@
package contrast
import (
"fmt"
"image"
"strconv"
"github.com/anthonynsimon/bild/adjust"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "contrast"
}
func (impl) Apply(img image.Image, args string) (image.Image, error) {
var change float64 = 0.1
if args != "" {
f64, err := strconv.ParseFloat(args, 64)
if err != nil || f64 < -1 || f64 > 1 || f64 == 0 {
return nil, fmt.Errorf("invalid contrast change: %s", args)
}
change = f64
}
logx.Printf(" applying contrast (change=%.f)\n", change)
return adjust.Contrast(img, change), nil
}

103
internal/effects/effects.go Normal file
View File

@@ -0,0 +1,103 @@
package effects
import (
"fmt"
"image"
"strings"
"github.com/urfave/cli/v3"
)
type Effect interface {
String() string
Apply(image.Image, string) (image.Image, error)
}
type EffectConfig struct {
Effect Effect
Arguments string
}
var (
apply string
names []string
registry = make(map[string]Effect)
)
func Register(e Effect) {
name := e.String()
names = append(names, name)
registry[name] = e
}
func HasEffects() bool {
return len(registry) > 0
}
func Flags(flags []cli.Flag) []cli.Flag {
if len(registry) == 0 {
return flags
}
return append(flags,
&cli.StringFlag{
Name: "effects",
Aliases: []string{"e"},
Usage: fmt.Sprintf("list of effects to apply (%s)", strings.Join(names, ", ")),
Value: "",
Destination: &apply,
},
)
}
func ApplyAll(img image.Image) (image.Image, int, error) {
if apply == "" {
return img, 0, nil
}
list, err := Parse()
if err != nil {
return nil, 0, err
} else if len(list) == 0 {
return img, 0, nil
}
for _, e := range list {
img, err = e.Effect.Apply(img, e.Arguments)
if err != nil {
return nil, 0, err
}
}
return img, len(list), nil
}
func Parse() ([]EffectConfig, error) {
var result []EffectConfig
for entry := range strings.SplitSeq(apply, ",") {
var (
name = entry
arguments string
)
if index := strings.Index(entry, ":"); index != -1 {
name = entry[:index]
arguments = entry[index+1:]
}
effect, ok := registry[name]
if !ok {
return nil, fmt.Errorf("invalid effect: %s", name)
}
result = append(result, EffectConfig{
Effect: effect,
Arguments: arguments,
})
}
return result, nil
}

View File

@@ -0,0 +1,25 @@
package grayscale
import (
"image"
"github.com/anthonynsimon/bild/effect"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "grayscale"
}
func (impl) Apply(img image.Image, _ string) (image.Image, error) {
logx.Printf(" applying grayscale\n")
return effect.Grayscale(img), nil
}

View File

@@ -0,0 +1,38 @@
package hue
import (
"fmt"
"image"
"strconv"
"github.com/anthonynsimon/bild/adjust"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "hue"
}
func (impl) Apply(img image.Image, args string) (image.Image, error) {
var change int64 = 10
if args != "" {
i64, err := strconv.ParseInt(args, 10, 64)
if err != nil || i64 < -360 || i64 > 360 || i64 == 0 {
return nil, fmt.Errorf("invalid hue change: %s", args)
}
change = i64
}
logx.Printf(" applying hue (change=%d)\n", change)
return adjust.Hue(img, int(change)), nil
}

View File

@@ -0,0 +1,25 @@
package invert
import (
"image"
"github.com/anthonynsimon/bild/effect"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "invert"
}
func (impl) Apply(img image.Image, _ string) (image.Image, error) {
logx.Printf(" applying invert\n")
return effect.Invert(img), nil
}

View File

@@ -0,0 +1,38 @@
package saturation
import (
"fmt"
"image"
"strconv"
"github.com/anthonynsimon/bild/adjust"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "saturation"
}
func (impl) Apply(img image.Image, args string) (image.Image, error) {
var change float64 = 0.1
if args != "" {
f64, err := strconv.ParseFloat(args, 64)
if err != nil || f64 < -1 || f64 > 1 || f64 == 0 {
return nil, fmt.Errorf("invalid saturation change: %s", args)
}
change = f64
}
logx.Printf(" applying saturation (change=%.f)\n", change)
return adjust.Saturation(img, change), nil
}

View File

@@ -0,0 +1,25 @@
package sepia
import (
"image"
"github.com/anthonynsimon/bild/effect"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "sepia"
}
func (impl) Apply(img image.Image, _ string) (image.Image, error) {
logx.Printf(" applying sepia\n")
return effect.Sepia(img), nil
}

View File

@@ -0,0 +1,25 @@
package sharpen
import (
"image"
"github.com/anthonynsimon/bild/effect"
"github.com/coalaura/ffwebp/internal/effects"
"github.com/coalaura/ffwebp/internal/logx"
)
type impl struct{}
func init() {
effects.Register(impl{})
}
func (impl) String() string {
return "sharpen"
}
func (impl) Apply(img image.Image, _ string) (image.Image, error) {
logx.Printf(" applying sharpen\n")
return effect.Sharpen(img), nil
}