Skip to content

Commit

Permalink
colors: add threshold filter
Browse files Browse the repository at this point in the history
  • Loading branch information
disintegration committed Oct 5, 2017
1 parent fa2cc98 commit be798eb
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ gift.New().DrawAt(dstImage, fgImage, image.Pt(100, 100), gift.OverOperator)
- Sepia(percentage float32)
- Sigmoid(midpoint, factor float32)
- Sobel()
- Threshold(percentage float32)
- UnsharpMask(sigma, amount, threshold float32)


Expand Down
15 changes: 15 additions & 0 deletions colors.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,21 @@ func ColorBalance(percentageRed, percentageGreen, percentageBlue float32) Filter
}
}

// Threshold creates a filter that applies black/white thresholding to the image.
// The percentage parameter must be in range (0, 100).
func Threshold(percentage float32) Filter {
p := minf32(maxf32(percentage, 0), 100) / 100
return &colorFilter{
fn: func(px pixel) pixel {
y := 0.299*px.r + 0.587*px.g + 0.114*px.b
if y > p {
return pixel{1, 1, 1, px.a}
}
return pixel{0, 0, 0, px.a}
},
}
}

// ColorFunc creates a filter that changes the colors of an image using custom function.
// The fn parameter specifies a function that takes red, green, blue and alpha channels of a pixel
// as float32 values in range (0, 1) and returns the modified channel values.
Expand Down
79 changes: 79 additions & 0 deletions colors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,85 @@ func TestColorBalance(t *testing.T) {
}
}

func TestThreshold(t *testing.T) {
testData := []struct {
desc string
percentage float32
srcb, dstb image.Rectangle
srcPix, dstPix []uint8
}{
{
"threshold -1",
-1,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0xff, 0xff, 0xff, 0xff, 0xff},
},
{
"threshold 0",
0,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0xff, 0xff, 0xff, 0xff, 0xff},
},
{
"threshold 30",
30,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
},
{
"threshold 50",
50,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0x00, 0x00, 0xff, 0xff, 0xff},
},
{
"threshold 90",
90,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
},
{
"threshold 100",
100,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
},
{
"threshold 101",
101,
image.Rect(-1, -1, 5, 0),
image.Rect(0, 0, 6, 1),
[]uint8{0x00, 0x33, 0x66, 0x99, 0xcc, 0xff},
[]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
},
}

for _, d := range testData {
src := image.NewGray(d.srcb)
src.Pix = d.srcPix

f := Threshold(d.percentage)
dst := image.NewGray(f.Bounds(src.Bounds()))
f.Draw(dst, src, nil)

if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
}
}
}

func TestColorFunc(t *testing.T) {
testData := []struct {
desc string
Expand Down

0 comments on commit be798eb

Please sign in to comment.