From cb6ae6d37158be9ba71e1d7dc92a7dcbe8c267d1 Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 19 Jun 2025 12:50:28 +0200 Subject: [PATCH] png --- internal/codec/png/png.go | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 internal/codec/png/png.go diff --git a/internal/codec/png/png.go b/internal/codec/png/png.go new file mode 100644 index 0000000..203399e --- /dev/null +++ b/internal/codec/png/png.go @@ -0,0 +1,88 @@ +package png + +import ( + "bytes" + "fmt" + "image" + "image/png" + "io" + + "github.com/coalaura/ffwebp/internal/codec" + "github.com/coalaura/ffwebp/internal/opts" + "github.com/urfave/cli/v3" +) + +var ( + compression int +) + +type impl struct{} + +func init() { + codec.Register(impl{}) +} + +func (impl) Name() string { + return "png" +} + +func (impl) Extensions() []string { + return []string{"png"} +} + +func (impl) Flags(flags []cli.Flag) []cli.Flag { + return append(flags, &cli.IntFlag{ + Name: "png.compression", + Usage: "PNG: compression level (0=default, 1=none, 2=speed, 3=best)", + Value: 0, + Destination: &compression, + Validator: func(value int) error { + if value < 0 || value > 4 { + return fmt.Errorf("invalid compression level: %q", value) + } + + return nil + }, + }) +} + +func (impl) Sniff(reader io.ReaderAt) (int, error) { + magic := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A} + + buf := make([]byte, len(magic)) + + if _, err := reader.ReadAt(buf, 0); err != nil { + return 0, err + } + + if bytes.Equal(buf, magic) { + return 100, nil + } + + return 0, nil +} + +func (impl) Decode(reader io.Reader) (image.Image, error) { + return png.Decode(reader) +} + +func (impl) Encode(writer io.Writer, img image.Image, _ opts.Common) error { + encoder := png.Encoder{ + CompressionLevel: compressionLevel(compression), + } + + return encoder.Encode(writer, img) +} + +func compressionLevel(level int) png.CompressionLevel { + switch level { + case 1: + return png.NoCompression + case 2: + return png.BestSpeed + case 3: + return png.BestCompression + default: + return png.DefaultCompression + } +}