diff --git a/Makefile b/Makefile index bdbf47c6..acc8a41f 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,6 @@ build: -X github.com/thoas/picfit/constants.Branch=$(branch) \ -X github.com/thoas/picfit/constants.Revision=$(commit) \ -X 'github.com/thoas/picfit/constants.BuildTime=$(now)' \ - -X 'github.com/thoas/picfit/constants.LatestCommitMessage=$(commitMessage)' \ -X 'github.com/thoas/picfit/constants.Compiler=$(compiler)'" -o $(BIN_DIR)/picfit ./cmd/picfit/main.go @(echo "-> picfit binary created") diff --git a/README.rst b/README.rst index f0f9744b..f98c2bc1 100644 --- a/README.rst +++ b/README.rst @@ -431,6 +431,7 @@ picfit currently supports the following image formats: - ``image/png`` with the keyword ``png`` - ``image/gif`` with the keyword ``gif`` - ``image/bmp`` with the keyword ``bmp`` +- ``image/webp`` with the keyword ``webp`` Operations ========== diff --git a/engine/backend/backend.go b/engine/backend/backend.go index 560b4aff..fc098cd0 100644 --- a/engine/backend/backend.go +++ b/engine/backend/backend.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/go-spectest/imaging" "github.com/pkg/errors" "github.com/thoas/picfit/image" ) @@ -16,8 +15,7 @@ var MethodNotImplementedError = errors.New("Not implemented") type Options struct { Color string Degree int - Filter string - Format imaging.Format + Format image.Format Height int Images []image.ImageFile Position string diff --git a/engine/backend/goimage.go b/engine/backend/goimage.go index dba08d9d..a6005cdc 100644 --- a/engine/backend/goimage.go +++ b/engine/backend/goimage.go @@ -20,6 +20,7 @@ import ( imagefile "github.com/thoas/picfit/image" + "github.com/chai2010/webp" "golang.org/x/image/bmp" "golang.org/x/image/tiff" ) @@ -88,7 +89,7 @@ func (e *GoImage) Flip(ctx context.Context, img *imagefile.ImageFile, options *O } func (e *GoImage) Fit(ctx context.Context, img *imagefile.ImageFile, options *Options) ([]byte, error) { - if options.Format == imaging.GIF { + if options.Format == imagefile.GIF { content, err := e.transformGIF(img, options, imaging.Thumbnail) if err != nil { return nil, err @@ -105,6 +106,7 @@ func (e *GoImage) Fit(ctx context.Context, img *imagefile.ImageFile, options *Op return e.transform(image, options, imaging.Fit) } + func (e *GoImage) Effect(ctx context.Context, img *imagefile.ImageFile, options *Options) ([]byte, error) { image, err := e.source(img) if err != nil { @@ -122,7 +124,7 @@ func (e *GoImage) Effect(ctx context.Context, img *imagefile.ImageFile, options return nil, MethodNotImplementedError } -func (e *GoImage) toBytes(img image.Image, format imaging.Format, quality int) ([]byte, error) { +func (e *GoImage) toBytes(img image.Image, format imagefile.Format, quality int) ([]byte, error) { var buf bytes.Buffer if err := encode(&buf, img, format, quality); err != nil { @@ -182,7 +184,7 @@ func (e *GoImage) transformGIF(img *imagefile.ImageFile, options *Options, trans } func (e *GoImage) resize(img *imagefile.ImageFile, options *Options, trans transformation) ([]byte, error) { - if options.Format == imaging.GIF { + if options.Format == imagefile.GIF { content, err := e.transformGIF(img, options, trans) if err != nil { return nil, err @@ -200,6 +202,10 @@ func (e *GoImage) resize(img *imagefile.ImageFile, options *Options, trans trans } func (e *GoImage) transform(img image.Image, options *Options, trans transformation) ([]byte, error) { + if options.Height == 0 && options.Width == 0 { + return e.toBytes(img, options.Format, options.Quality) + } + return e.toBytes(scale(img, options, trans), options.Format, options.Quality) } @@ -238,10 +244,10 @@ func imageToPaletted(img image.Image) *image.Paletted { return pm } -func encode(w io.Writer, img image.Image, format imaging.Format, quality int) error { +func encode(w io.Writer, img image.Image, format imagefile.Format, quality int) error { var err error switch format { - case imaging.JPEG: + case imagefile.JPEG: var rgba *image.RGBA if nrgba, ok := img.(*image.NRGBA); ok { if nrgba.Opaque() { @@ -258,14 +264,16 @@ func encode(w io.Writer, img image.Image, format imaging.Format, quality int) er err = jpeg.Encode(w, img, &jpeg.Options{Quality: quality}) } - case imaging.PNG: + case imagefile.PNG: err = png.Encode(w, img) - case imaging.GIF: + case imagefile.GIF: err = gif.Encode(w, img, &gif.Options{NumColors: 256}) - case imaging.TIFF: + case imagefile.TIFF: err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true}) - case imaging.BMP: + case imagefile.BMP: err = bmp.Encode(w, img) + case imagefile.WEBP: + err = webp.Encode(w, img, &webp.Options{Quality: float32(quality)}) default: err = imaging.ErrUnsupportedFormat } diff --git a/engine/backend/goimage_flat.go b/engine/backend/goimage_flat.go index ed4821e2..1e1c5b19 100644 --- a/engine/backend/goimage_flat.go +++ b/engine/backend/goimage_flat.go @@ -27,7 +27,7 @@ func (e *GoImage) Flat(ctx context.Context, backgroundFile *imagefile.ImageFile, } } - if options.Format == imaging.GIF { + if options.Format == imagefile.GIF { g, err := gif.DecodeAll(bytes.NewReader(backgroundFile.Source)) if err != nil { return nil, err diff --git a/engine/constants.go b/engine/constants.go index d99acbe3..58b3e88d 100644 --- a/engine/constants.go +++ b/engine/constants.go @@ -15,5 +15,6 @@ var ( "image/gif", "image/jpeg", "image/png", + "image/webp", } ) diff --git a/go.mod b/go.mod index c761c2b0..d386468a 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( ) require ( + github.com/chai2010/webp v1.1.1 github.com/google/uuid v1.3.0 github.com/prometheus/client_golang v1.14.0 golang.org/x/sync v0.7.0 diff --git a/go.sum b/go.sum index f75fcd24..273e791a 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk= +github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= diff --git a/image/formats.go b/image/formats.go new file mode 100644 index 00000000..d5831ee1 --- /dev/null +++ b/image/formats.go @@ -0,0 +1,13 @@ +package image + +type Format int + +// Image file formats. +const ( + JPEG Format = iota + PNG + GIF + TIFF + BMP + WEBP +) diff --git a/parameters.go b/parameters.go index a15911e0..2a1988fb 100644 --- a/parameters.go +++ b/parameters.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - "github.com/go-spectest/imaging" "github.com/pkg/errors" "github.com/ulule/gostorages" @@ -25,12 +24,14 @@ const ( defaultWidth = 0 ) -var formats = map[string]imaging.Format{ - "bmp": imaging.BMP, - "gif": imaging.GIF, - "jpeg": imaging.JPEG, - "jpg": imaging.JPEG, - "png": imaging.PNG, +var formats = map[string]image.Format{ + "bmp": image.BMP, + "gif": image.GIF, + "jpeg": image.JPEG, + "jpg": image.JPEG, + "png": image.PNG, + "tiff": image.TIFF, + "webp": image.WEBP, } type Parameters struct {