From 2803021feffcc403dba4cce2787f5f9e1ee956ba Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Jan 2022 16:51:03 +0100 Subject: [PATCH] Add fit image step --- README.md | 16 ++++++++++++ pipelines/executable_step.go | 15 +++++++++++ pipelines/pipeline_test.go | 50 +++++++++++++++++++++++++++++++++++- pipelines/step.go | 8 ++++++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40fa5ec..9b6676f 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,22 @@ Convert the colorspace of an image into grayscale. } ``` +#### Fit + +Scales down the image to fit the specified maximum width and height. + +**Step definition**: + +```json +{ + "type": 4, + "options": { + "height": 300, + "width": 200 + } +} +``` + ## Authors - [Fabian Vowie](https://gogs.informatik.hs-fulda.de/FabianVowie) diff --git a/pipelines/executable_step.go b/pipelines/executable_step.go index c0bfedb..494e294 100644 --- a/pipelines/executable_step.go +++ b/pipelines/executable_step.go @@ -74,3 +74,18 @@ func (s GrayscaleImageStep) Execute(src image.Image) (image.Image, error) { src = imaging.Grayscale(src) return src, nil } + +// Fit image + +type FitImageStep struct { + Step + Options struct { + Height int `json:"height"` + Width int `json:"width"` + } `json:"options"` +} + +func (s FitImageStep) Execute(src image.Image) (image.Image, error) { + src = imaging.Fit(src, s.Options.Width, s.Options.Height, imaging.Lanczos) + return src, nil +} diff --git a/pipelines/pipeline_test.go b/pipelines/pipeline_test.go index 63a9f7b..856f235 100644 --- a/pipelines/pipeline_test.go +++ b/pipelines/pipeline_test.go @@ -239,7 +239,7 @@ func TestExecuteSteps(t *testing.T) { }) t.Run("Image flip step direction validation is successful", func(t *testing.T) { - const Bucket string = "pipeline_test_06" + const Bucket string = "pipeline_test_07" const Payload string = `{ "name": "example pipeline", "type": 1, @@ -316,6 +316,54 @@ func TestExecuteSteps(t *testing.T) { os.Remove(storageProvider.GetPath(Bucket, "source.jpg")) os.Remove(storageProvider.GetPath(Bucket, dest)) }) + + t.Run("Image fit step is successful", func(t *testing.T) { + const Bucket string = "pipeline_test_08" + const Payload string = `{ + "name": "example pipeline", + "type": 1, + "removeMetadata": false, + "steps": [ + { + "name": "fit", + "type": 4, + "options": { + "width": 300, + "height": 200 + } + } + ] + }` + + wd, _ := os.Getwd() + pipe := DeserializePipelines([][]byte{[]byte(Payload)})[0] + + storageProvider := storage.GetFileSystemStorageProvider("test", "..") + + // copy test file to storage bucket + _, err := storageProvider.StoreExisting(Bucket, "source.jpg", filepath.Join(wd, "../tests/files/900x900.jpg")) + assert.Nil(t, err, "Test file should be readable") + assert.FileExists(t, storageProvider.GetPath(Bucket, "source.jpg")) + + // run pipeline steps + dest, err := pipe.Run("source.jpg", Bucket, storageProvider) + assert.Nil(t, err) + assert.FileExists(t, storageProvider.GetPath(Bucket, dest)) + + // read image config + file, err := storageProvider.OpenFile(Bucket, dest) + assert.Nil(t, err) + + imgConf, _, err := image.DecodeConfig(file) + assert.Nil(t, err) + + assert.Equal(t, 200, imgConf.Width) + assert.Equal(t, 200, imgConf.Height) + + // clean up + os.Remove(storageProvider.GetPath(Bucket, "source.jpg")) + os.Remove(storageProvider.GetPath(Bucket, dest)) + }) } // output options diff --git a/pipelines/step.go b/pipelines/step.go index 9d60844..4799b64 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -12,6 +12,7 @@ const ( TypeRotateImageStep TypeFlipImageStep TypeGrayscaleImageStep + TypeFitImageStep ) type Step struct { @@ -44,6 +45,13 @@ func (s Step) GetExecutable() (IExecutableStep, error) { } return step, nil + case TypeFitImageStep: + step := FitImageStep{} + if err := json.Unmarshal(s.Options, &step.Options); err != nil { + return nil, err + } + return step, nil + case TypeGrayscaleImageStep: return GrayscaleImageStep{}, nil }