Skip to content

Commit

Permalink
feat: Add blur (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
VivienCormier authored Mar 8, 2024
1 parent 6cc0c08 commit b2561b5
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 28 deletions.
13 changes: 12 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ Parameters to call the picfit service are:

.. code-block:: html

<img src="http://localhost:3001/{method}?url={url}&path={path}&w={width}&h={height}&upscale={upscale}&sig={sig}&op={operation}&fmt={format}&q={quality}&deg={degree}&pos={position}"
<img src="http://localhost:3001/{method}?url={url}&path={path}&w={width}&h={height}&upscale={upscale}&sig={sig}&op={operation}&fmt={format}&q={quality}&deg={degree}&pos={position}&filter={filter}"

- **path** - The filepath to load the image using your source storage
- **operation** - The operation to perform, see Operations_
Expand All @@ -390,6 +390,7 @@ Parameters to call the picfit service are:
- **quality** - The quality to save the image, by default the quality will be the highest possible, it will be only applied on ``JPEG`` format
- **degree** - The degree (``90``, ``180``, ``270``) to rotate the image
- **position** - The position to flip the image
- **filter** - The filter for the effect operation (``blur``)

To use this service, include the service url as replacement
for your images, for example:
Expand Down Expand Up @@ -491,6 +492,16 @@ Flat can be used only with the [multiple operation system].

In order to understand the Flat operation, please read the following `docs <https://github.com/thoas/picfit/blob/superpose-images/docs/flat.md>`_.

Effect
------

Add effect to the given image.

- **filter** - The desired effect : ``blur``

You have to pass the ``effect`` value to the ``op`` parameter
to use this operation.

Methods
=======

Expand Down
6 changes: 6 additions & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ var StickPositions = []string{
TopRight,
}

const FilterBlur = "blur"

var Filters = []string{
FilterBlur,
}

const ModifiedTimeFormat = time.RFC1123

const RequestIDCtx = "request-id"
4 changes: 3 additions & 1 deletion engine/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"fmt"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"
"github.com/pkg/errors"
"github.com/thoas/picfit/image"
)
Expand All @@ -16,6 +16,7 @@ var MethodNotImplementedError = errors.New("Not implemented")
type Options struct {
Color string
Degree int
Filter string
Format imaging.Format
Height int
Images []image.ImageFile
Expand All @@ -33,6 +34,7 @@ func (o Options) String() string {

// Engine is an interface to define an image engine
type Backend interface {
Effect(ctx context.Context, img *image.ImageFile, options *Options) ([]byte, error)
Fit(ctx context.Context, img *image.ImageFile, options *Options) ([]byte, error)
Flat(ctx context.Context, background *image.ImageFile, options *Options) ([]byte, error)
Flip(ctx context.Context, img *image.ImageFile, options *Options) ([]byte, error)
Expand Down
2 changes: 1 addition & 1 deletion engine/backend/exif.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"image"
"io"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"
"github.com/rwcarlsen/goexif/exif"
_ "golang.org/x/image/webp"
)
Expand Down
5 changes: 5 additions & 0 deletions engine/backend/gifsicle.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ func (b *Gifsicle) Fit(ctx context.Context, img *image.ImageFile, options *Optio
return nil, MethodNotImplementedError
}

// Effect implements Backend.
func (b *Gifsicle) Effect(ctx context.Context, img *image.ImageFile, options *Options) ([]byte, error) {
return nil, MethodNotImplementedError
}

// Flat implements Backend.
func (b *Gifsicle) Flat(ctx context.Context, img *image.ImageFile, options *Options) ([]byte, error) {
return nil, MethodNotImplementedError
Expand Down
21 changes: 20 additions & 1 deletion engine/backend/goimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"context"
"fmt"
"github.com/thoas/go-funk"
"github.com/thoas/picfit/constants"
"image"
"image/color/palette"
"image/draw"
Expand All @@ -13,7 +15,7 @@ import (
"io"
"math"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"

imagefile "github.com/thoas/picfit/image"

Expand Down Expand Up @@ -102,6 +104,23 @@ 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 {
return nil, err
}
width, height := imageSize(image)
size := funk.MaxInt([]int{width, height})
sigma := size / 20

switch options.Filter {
case constants.FilterBlur:
return e.toBytes(imaging.Blur(image, float64(sigma)), options.Format, options.Quality)
}

return nil, MethodNotImplementedError
}

func (e *GoImage) toBytes(img image.Image, format imaging.Format, quality int) ([]byte, error) {
var buf bytes.Buffer

Expand Down
2 changes: 1 addition & 1 deletion engine/backend/goimage_flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"strconv"
"strings"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"
colorful "github.com/lucasb-eyer/go-colorful"

"github.com/thoas/picfit/constants"
Expand Down
7 changes: 5 additions & 2 deletions engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package engine
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/thoas/picfit/engine/backend"
"github.com/thoas/picfit/engine/config"
"github.com/thoas/picfit/image"
Expand Down Expand Up @@ -124,7 +125,7 @@ func (e Engine) Transform(ctx context.Context, output *image.ImageFile, operatio
output.Source = processed
break
}
if err != backend.MethodNotImplementedError {
if !errors.Is(err, backend.MethodNotImplementedError) {
return nil, err
}
}
Expand Down Expand Up @@ -152,7 +153,9 @@ func operate(ctx context.Context, b backend.Backend, img *image.ImageFile, opera
return b.Fit(ctx, img, options)
case Flat:
return b.Flat(ctx, img, options)
case Effect:
return b.Effect(ctx, img, options)
default:
return nil, fmt.Errorf("Operation not found for %s", operation)
return nil, fmt.Errorf("operation not found for %s", operation)
}
}
2 changes: 2 additions & 0 deletions engine/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ func (o Operation) String() string {
}

const (
Effect = Operation("effect")
Fit = Operation("fit")
Flat = Operation("flat")
Flip = Operation("flip")
Expand All @@ -19,6 +20,7 @@ const (
)

var Operations = map[string]Operation{
Effect.String(): Effect,
Fit.String(): Fit,
Flat.String(): Flat,
Flip.String(): Flip,
Expand Down
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cstockton/go-conv v0.0.0-20170524002450-66a2b2ba36e1
github.com/davecgh/go-spew v1.1.1
github.com/disintegration/imaging v1.6.2
github.com/getsentry/sentry-go v0.19.0
github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/validator/v10 v10.15.4 // indirect
github.com/go-spectest/imaging v1.0.6
github.com/k0kubun/pp v3.0.1+incompatible
github.com/lucasb-eyer/go-colorful v0.0.0-20180709185858-c7842319cf3a
github.com/mattn/go-isatty v0.0.19 // indirect
Expand All @@ -25,16 +25,17 @@ require (
github.com/ulule/gokvstores v0.1.1-0.20221229151109-3bd12fb72ebe
github.com/ulule/gostorages v0.2.5-0.20230920134537-c63293fd790c
github.com/urfave/cli v1.22.10
golang.org/x/image v0.10.0
golang.org/x/image v0.13.0
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 // indirect
gopkg.in/fukata/golang-stats-api-handler.v1 v1.0.0
)

require (
github.com/go-spectest/imaging v1.0.6
github.com/google/uuid v1.3.0
github.com/prometheus/client_golang v1.14.0
golang.org/x/sync v0.1.0
golang.org/x/sync v0.4.0
)

require (
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ github.com/go-playground/validator/v10 v10.15.4 h1:zMXza4EpOdooxPel5xDqXEdXG5r+W
github.com/go-playground/validator/v10 v10.15.4/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-spectest/imaging v1.0.6 h1:b7qzcXLs1p9uZMjAKO+oe+a6EGo5JbwPDkcWafmTnX8=
github.com/go-spectest/imaging v1.0.6/go.mod h1:/AyhBt5HEFGDPy2AxP+hcV5NH8QQpftJP9g3yGOVtvs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
Expand Down Expand Up @@ -507,6 +509,8 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.10.0 h1:gXjUUtwtx5yOE0VKWq1CH4IJAClq4UGgUA3i+rpON9M=
golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down Expand Up @@ -610,6 +614,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
34 changes: 17 additions & 17 deletions parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package picfit
import (
"context"
"fmt"
"slices"
"strconv"
"strings"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"
"github.com/pkg/errors"
"github.com/ulule/gostorages"

Expand Down Expand Up @@ -197,17 +198,10 @@ func (p Processor) newBackendOptionsFromParameters(operation engine.Operation, q
return nil, fmt.Errorf("Parameter \"pos\" not found in query string")
}

stick, _ := qs["stick"].(string)
if stick != "" {
var exists bool
for i := range constants.StickPositions {
if stick == constants.StickPositions[i] {
exists = true
break
}
}
if !exists {
return nil, fmt.Errorf("Parameter \"stick\" has wrong value. Available values are: %v", constants.StickPositions)
stick, ok := qs["stick"].(string)
if ok {
if !slices.Contains(constants.StickPositions, stick) {
return nil, fmt.Errorf("parameter \"stick\" has wrong value. Available values are: %v", constants.StickPositions)
}
}

Expand Down Expand Up @@ -241,14 +235,20 @@ func (p Processor) newBackendOptionsFromParameters(operation engine.Operation, q
}
}

filter, ok := qs["filter"].(string)
if ok && !slices.Contains(constants.Filters, filter) {
return nil, fmt.Errorf("parameter \"filter\" has wrong value. Available values are: %v", constants.Filters)
}

return &backend.Options{
Width: width,
Color: color,
Degree: degree,
Filter: filter,
Height: height,
Upscale: upscale,
Position: position,
Stick: stick,
Quality: quality,
Degree: degree,
Color: color,
Stick: stick,
Upscale: upscale,
Width: width,
}, nil
}
2 changes: 1 addition & 1 deletion processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/cstockton/go-conv"

"github.com/disintegration/imaging"
"github.com/go-spectest/imaging"

"github.com/stretchr/testify/assert"

Expand Down

0 comments on commit b2561b5

Please sign in to comment.