143 lines
3.3 KiB
Go
143 lines
3.3 KiB
Go
package application
|
|
|
|
import (
|
|
"bytes"
|
|
"image"
|
|
"image/color"
|
|
"image/draw"
|
|
"image/png"
|
|
"testing"
|
|
)
|
|
|
|
func TestApplyAnnotationsDrawsIntoPNG(t *testing.T) {
|
|
src := image.NewRGBA(image.Rect(0, 0, 40, 40))
|
|
draw.Draw(src, src.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
|
|
|
|
var buf bytes.Buffer
|
|
if err := png.Encode(&buf, src); err != nil {
|
|
t.Fatalf("encode source: %v", err)
|
|
}
|
|
|
|
out, err := ApplyAnnotations(buf.Bytes(), []Annotation{
|
|
{
|
|
Tool: "rect",
|
|
Color: "#ef4444",
|
|
Points: []Point{
|
|
{X: 5, Y: 5},
|
|
{X: 30, Y: 30},
|
|
},
|
|
},
|
|
}, 1)
|
|
if err != nil {
|
|
t.Fatalf("apply annotations: %v", err)
|
|
}
|
|
|
|
img, err := png.Decode(bytes.NewReader(out))
|
|
if err != nil {
|
|
t.Fatalf("decode output: %v", err)
|
|
}
|
|
if got := color.RGBAModel.Convert(img.At(5, 5)).(color.RGBA); got.R != 0xef || got.G != 0x44 || got.B != 0x44 {
|
|
t.Fatalf("expected annotated pixel at rectangle edge, got %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestApplyAnnotationsNoAnnotationsReturnsOriginalBytes(t *testing.T) {
|
|
original := []byte("not decoded when no annotations")
|
|
out, err := ApplyAnnotations(original, nil, 1)
|
|
if err != nil {
|
|
t.Fatalf("apply annotations: %v", err)
|
|
}
|
|
if !bytes.Equal(out, original) {
|
|
t.Fatalf("expected original bytes")
|
|
}
|
|
}
|
|
|
|
func TestApplyAnnotationsDrawsTextIntoPNG(t *testing.T) {
|
|
src := image.NewRGBA(image.Rect(0, 0, 120, 80))
|
|
draw.Draw(src, src.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
|
|
|
|
var buf bytes.Buffer
|
|
if err := png.Encode(&buf, src); err != nil {
|
|
t.Fatalf("encode source: %v", err)
|
|
}
|
|
|
|
out, err := ApplyAnnotations(buf.Bytes(), []Annotation{
|
|
{
|
|
Tool: "text",
|
|
Color: "#ef4444",
|
|
Points: []Point{
|
|
{X: 10, Y: 10},
|
|
},
|
|
Text: "T",
|
|
},
|
|
}, 1)
|
|
if err != nil {
|
|
t.Fatalf("apply annotations: %v", err)
|
|
}
|
|
|
|
img, err := png.Decode(bytes.NewReader(out))
|
|
if err != nil {
|
|
t.Fatalf("decode output: %v", err)
|
|
}
|
|
found := false
|
|
for y := 8; y < 40 && !found; y++ {
|
|
for x := 8; x < 40; x++ {
|
|
got := color.RGBAModel.Convert(img.At(x, y)).(color.RGBA)
|
|
if got.R > 180 && got.G < 180 && got.B < 180 {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("expected red text pixels near annotation point")
|
|
}
|
|
}
|
|
|
|
func TestApplyAnnotationsWithScaleDrawsTextAtDevicePosition(t *testing.T) {
|
|
src := image.NewRGBA(image.Rect(0, 0, 220, 120))
|
|
draw.Draw(src, src.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
|
|
|
|
var buf bytes.Buffer
|
|
if err := png.Encode(&buf, src); err != nil {
|
|
t.Fatalf("encode source: %v", err)
|
|
}
|
|
|
|
out, err := ApplyAnnotationsWithScale(buf.Bytes(), []Annotation{
|
|
{
|
|
Tool: "text",
|
|
Color: "#ef4444",
|
|
Points: []Point{{X: 50, Y: 20}},
|
|
Text: "T",
|
|
FontSize: 20,
|
|
},
|
|
}, 2, 2)
|
|
if err != nil {
|
|
t.Fatalf("apply annotations: %v", err)
|
|
}
|
|
|
|
img, err := png.Decode(bytes.NewReader(out))
|
|
if err != nil {
|
|
t.Fatalf("decode output: %v", err)
|
|
}
|
|
minX := 999
|
|
found := false
|
|
for y := 0; y < img.Bounds().Dy(); y++ {
|
|
for x := 0; x < img.Bounds().Dx(); x++ {
|
|
got := color.RGBAModel.Convert(img.At(x, y)).(color.RGBA)
|
|
if got.R > 180 && got.G < 180 && got.B < 180 {
|
|
found = true
|
|
if x < minX {
|
|
minX = x
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("expected red text pixels")
|
|
}
|
|
if minX < 90 {
|
|
t.Fatalf("expected text to be drawn near scaled x=100, min red x=%d", minX)
|
|
}
|
|
}
|