Skip to content

Commit

Permalink
feat(image): add result utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
bounoable committed Sep 5, 2022
1 parent 30b2a7b commit 6ff2677
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 9 deletions.
53 changes: 53 additions & 0 deletions image/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package image

import (
"image"
"strconv"
"strings"

"github.com/modernice/media-tools/image/internal"
)
Expand Down Expand Up @@ -112,3 +114,54 @@ func (c *Compressor) Process(ctx ProcessorContext) ([]Processed, error) {

return out, nil
}

// CompressionName extracts the name of the [Compression] from the tags of a
// processed image.
func CompressionName(tags Tags) string {
if !tags.Contains(Compressed) {
return ""
}

for _, tag := range tags {
if !strings.HasPrefix(tag, "compression=") {
continue
}

parts := strings.Split(tag, ",")
compressionTag := parts[0]

return compressionTag[12:]
}

return ""
}

// CompressionQuality extracts the name of the compression quality from the tags
// of a processed image. If the tags to not provide the compression quality, -1
// is returned.
func CompressionQuality(tags Tags) int {
if !tags.Contains(Compressed) {
return -1
}

for _, tag := range tags {
if !strings.HasPrefix(tag, "compression=") {
continue
}

parts := strings.Split(tag, ",")
if len(parts) < 2 {
return -1
}

rawQuality := parts[1]
quality, err := strconv.Atoi(rawQuality[8:])
if err != nil {
return -1
}

return quality
}

return -1
}
63 changes: 54 additions & 9 deletions image/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"fmt"
"image"
"strings"
"regexp"

"github.com/modernice/media-tools/internal/slices"
)
Expand Down Expand Up @@ -62,6 +62,9 @@ func (ctx *processorContext) Image() Processed {
type PipelineResult struct {
// Images are the processed images.
Images []Processed

// Input is the original image that was passed to the [Pipeline].
Input image.Image
}

// Tags is a list of tags that Processors assigned to images in a [Pipeline].
Expand All @@ -72,6 +75,17 @@ func NewTags(tags ...string) Tags {
return slices.Unique(Tags(tags))
}

// Match returns the tags that match the given regular expression.
func (tags Tags) Match(re *regexp.Regexp) []string {
var out []string
for _, tag := range tags {
if re.MatchString(tag) {
out = append(out, tag)
}
}
return out
}

// Contains returns whether a tag is contained within tags.
func (tags Tags) Contains(tag string) bool {
return slices.Contains(tag, tags)
Expand All @@ -97,7 +111,7 @@ func (tags Tags) Without(remove ...string) Tags {
// Run runs the pipeline on an image and returns the [PipelineResult],
// containing the processed images.
func (pipeline Pipeline) Run(ctx context.Context, img image.Image) (PipelineResult, error) {
previous := []Processed{{Image: img, Original: true, Tags: NewTags(Original)}}
previous := []Processed{{Image: img, Tags: NewTags(Original), Original: true}}

for _, processor := range pipeline {
_previous := previous
Expand Down Expand Up @@ -126,15 +140,46 @@ func (pipeline Pipeline) Run(ctx context.Context, img image.Image) (PipelineResu
}
}

return PipelineResult{Images: previous}, nil
return PipelineResult{
Images: previous,
Input: img,
}, nil
}

// DimensionName extracts the dimension name from the tags of a processed image.
func DimensionName(tags Tags) string {
for _, tag := range tags {
if strings.HasPrefix(tag, "size=") {
return tag[5:]
// Original returns the processed image that is tagged as the original image.
// Depending on the [Pipeline], the original image may have been transformed
// by one or more [Processor]s. [PipelineResult.Input] is the actual image that
// was passed to [Pipeline.Run].
//
// If the [Pipeline] discarded the original image from its result, false is returned.
func (result PipelineResult) Original() (Processed, bool) {
images := result.Find(Original)
if len(images) > 0 {
return images[0], true
}
return Processed{}, false
}

// Find returns the processed images that gave the given tag.
func (result PipelineResult) Find(tag string) []Processed {
var out []Processed
for _, img := range result.Images {
if img.Tags.Contains(tag) {
out = append(out, img)
}
}
return out
}

// Match returns the processed images that have at least 1 tag that matches the
// given regular expression.
func (result PipelineResult) Match(re *regexp.Regexp) []Processed {
var out []Processed
for _, img := range result.Images {
matched := img.Tags.Match(re)
if len(matched) > 0 {
out = append(out, img)
}
}
return ""
return out
}
16 changes: 16 additions & 0 deletions image/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ func TestPipeline_Run(t *testing.T) {
t.Fatalf("second image should have tag %q", "compression=jpeg,quality=75")
}

if image.CompressionName(result.Images[1].Tags) != "jpeg" {
t.Fatalf("second image should have compression tag %q", "jpeg")
}

if image.CompressionQuality(result.Images[1].Tags) != 75 {
t.Fatalf("second image should have compression quality %d", 75)
}

lastIdx := len(result.Images) - 1
secondLastIdx := len(result.Images) - 2

Expand Down Expand Up @@ -109,6 +117,14 @@ func TestPipeline_Run(t *testing.T) {
t.Fatalf("last image should have tag %q", "compression=jpeg,quality=50")
}

if image.CompressionName(result.Images[lastIdx].Tags) != "jpeg" {
t.Fatalf("last image should have compression tag %q", "jpeg")
}

if image.CompressionQuality(result.Images[lastIdx].Tags) != 50 {
t.Fatalf("last image should have compression quality %d", 50)
}

for _, img := range result.Images {
if !img.Tags.Contains("foo") {
t.Fatalf("all images should have tag %q", "foo")
Expand Down
11 changes: 11 additions & 0 deletions image/resize.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package image
import (
"fmt"
"image"
"strings"

"github.com/disintegration/imaging"
"github.com/modernice/media-tools/internal/slices"
Expand Down Expand Up @@ -132,3 +133,13 @@ func (r *Resizer) Process(ctx ProcessorContext) ([]Processed, error) {

return append([]Processed{ctx.Image()}, processed...), nil
}

// DimensionName extracts the dimension name from the tags of a processed image.
func DimensionName(tags Tags) string {
for _, tag := range tags {
if strings.HasPrefix(tag, "size=") {
return tag[5:]
}
}
return ""
}

0 comments on commit 6ff2677

Please sign in to comment.