From 2803021feffcc403dba4cce2787f5f9e1ee956ba Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Jan 2022 16:51:03 +0100 Subject: [PATCH 1/3] 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 } From 85e5bf3efe8cce9349d868be20c9d71f468e2a1a Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Jan 2022 16:54:59 +0100 Subject: [PATCH 2/3] Add invert image step --- README.md | 12 ++++++++++ pipelines/executable_step.go | 11 +++++++++ pipelines/pipeline_test.go | 45 ++++++++++++++++++++++++++++++++++++ pipelines/step.go | 4 ++++ 4 files changed, 72 insertions(+) diff --git a/README.md b/README.md index 9b6676f..c601a7f 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,18 @@ Scales down the image to fit the specified maximum width and height. } ``` +#### Invert + +Invert image colors. + +**Step definition**: + +```json +{ + "type": 5 +} +``` + ## Authors - [Fabian Vowie](https://gogs.informatik.hs-fulda.de/FabianVowie) diff --git a/pipelines/executable_step.go b/pipelines/executable_step.go index 494e294..3909ad4 100644 --- a/pipelines/executable_step.go +++ b/pipelines/executable_step.go @@ -89,3 +89,14 @@ 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 } + +// Invert image + +type InvertImageStep struct { + Step +} + +func (s InvertImageStep) Execute(src image.Image) (image.Image, error) { + src = imaging.Invert(src) + return src, nil +} diff --git a/pipelines/pipeline_test.go b/pipelines/pipeline_test.go index 856f235..1c1ec00 100644 --- a/pipelines/pipeline_test.go +++ b/pipelines/pipeline_test.go @@ -364,6 +364,51 @@ func TestExecuteSteps(t *testing.T) { os.Remove(storageProvider.GetPath(Bucket, "source.jpg")) os.Remove(storageProvider.GetPath(Bucket, dest)) }) + + t.Run("Image invert step is successful", func(t *testing.T) { + const Bucket string = "pipeline_test_09" + const Payload string = `{ + "name": "example pipeline", + "type": 1, + "removeMetadata": false, + "steps": [ + { + "name": "invert", + "type": 5 + } + ] + }` + + 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, 900, imgConf.Width) + assert.Equal(t, 900, 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 4799b64..90919b3 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -13,6 +13,7 @@ const ( TypeFlipImageStep TypeGrayscaleImageStep TypeFitImageStep + TypeInvertImageStep ) type Step struct { @@ -52,6 +53,9 @@ func (s Step) GetExecutable() (IExecutableStep, error) { } return step, nil + case TypeInvertImageStep: + return InvertImageStep{}, nil + case TypeGrayscaleImageStep: return GrayscaleImageStep{}, nil } From 6c734a33d9a4ccaf296ca04c76f75f3ce693f8ee Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Jan 2022 16:59:51 +0100 Subject: [PATCH 3/3] Add blur image step --- README.md | 15 ++++++++++++ pipelines/executable_step.go | 14 +++++++++++ pipelines/pipeline_test.go | 46 ++++++++++++++++++++++++++++++++++++ pipelines/step.go | 8 +++++++ 4 files changed, 83 insertions(+) diff --git a/README.md b/README.md index c601a7f..7101b4e 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,21 @@ Invert image colors. } ``` +#### Blur + +Blur image using Gaussian functions. + +**Step definition**: + +```json +{ + "type": 6, + "options": { + "sigma": 50.0 + } +} +``` + ## Authors - [Fabian Vowie](https://gogs.informatik.hs-fulda.de/FabianVowie) diff --git a/pipelines/executable_step.go b/pipelines/executable_step.go index 3909ad4..c20c8c0 100644 --- a/pipelines/executable_step.go +++ b/pipelines/executable_step.go @@ -100,3 +100,17 @@ func (s InvertImageStep) Execute(src image.Image) (image.Image, error) { src = imaging.Invert(src) return src, nil } + +// Blur image + +type BlurImageStep struct { + Step + Options struct { + Sigma float64 `json:"sigma"` + } `json:"options"` +} + +func (s BlurImageStep) Execute(src image.Image) (image.Image, error) { + src = imaging.Blur(src, s.Options.Sigma) + return src, nil +} diff --git a/pipelines/pipeline_test.go b/pipelines/pipeline_test.go index 1c1ec00..d2d6857 100644 --- a/pipelines/pipeline_test.go +++ b/pipelines/pipeline_test.go @@ -409,6 +409,52 @@ func TestExecuteSteps(t *testing.T) { os.Remove(storageProvider.GetPath(Bucket, dest)) }) + t.Run("Image blur step is successful", func(t *testing.T) { + const Bucket string = "pipeline_test_10" + const Payload string = `{ + "name": "example pipeline", + "type": 1, + "removeMetadata": false, + "steps": [ + { + "name": "blur", + "type": 6, + "options": { + "sigma": 50.0 + } + } + ] + }` + + 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, 900, imgConf.Width) + assert.Equal(t, 900, 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 90919b3..f6d18d5 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -14,6 +14,7 @@ const ( TypeGrayscaleImageStep TypeFitImageStep TypeInvertImageStep + TypeBlurImageStep ) type Step struct { @@ -58,6 +59,13 @@ func (s Step) GetExecutable() (IExecutableStep, error) { case TypeGrayscaleImageStep: return GrayscaleImageStep{}, nil + + case TypeBlurImageStep: + step := BlurImageStep{} + if err := json.Unmarshal(s.Options, &step.Options); err != nil { + return nil, err + } + return step, nil } return nil, errors.New("invalid type")