diff --git a/pixelflut/api.go b/pixelflut/api.go index dc71841..3c0f422 100644 --- a/pixelflut/api.go +++ b/pixelflut/api.go @@ -12,7 +12,7 @@ import ( "github.com/SpeckiJ/Hochwasser/render" ) -var funmode = true +var funmode = false // Flut asynchronously sends the given image to pixelflut server at `address` // using `conns` connections. Pixels are sent column wise, unless `shuffle` @@ -22,11 +22,11 @@ func Flut(img *image.NRGBA, position image.Point, shuffle bool, address string, var cmds commands if funmode { // do a RGB split of white - imgmod := render.ImgReplaceColors(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0xff, 0, 0, 0xff}) + imgmod := render.ImgColorFilter(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0xff, 0, 0, 0xff}) cmds = append(cmds, commandsFromImage(imgmod, image.Pt(position.X-10, position.Y-10))...) - imgmod = render.ImgReplaceColors(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0, 0xff, 0, 0xff}) + imgmod = render.ImgColorFilter(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0, 0xff, 0, 0xff}) cmds = append(cmds, commandsFromImage(imgmod, image.Pt(position.X+10, position.Y))...) - imgmod = render.ImgReplaceColors(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0, 0, 0xff, 0xff}) + imgmod = render.ImgColorFilter(img, color.NRGBA{0xff, 0xff, 0xff, 0xff}, color.NRGBA{0, 0, 0xff, 0xff}) cmds = append(cmds, commandsFromImage(imgmod, image.Pt(position.X-10, position.Y+10))...) cmds = append(cmds, commandsFromImage(img, position)...) } else { diff --git a/render/image.go b/render/image.go index b9fe2ff..b3782f7 100644 --- a/render/image.go +++ b/render/image.go @@ -46,13 +46,17 @@ func ImgToNRGBA(img image.Image) *image.NRGBA { return r } -func ImgReplaceColors(img *image.NRGBA, from, to color.NRGBA) *image.NRGBA { +// ImgColorFilter replaces `from` with `to` in `img`, and sets all other pixels +// to color.Transparent +func ImgColorFilter(img *image.NRGBA, from, to color.NRGBA) *image.NRGBA { b := img.Bounds() r := image.NewNRGBA(b) for x := b.Min.X; x < b.Max.X; x++ { for y := b.Min.Y; y < b.Max.Y; y++ { if img.At(x, y) == from { r.SetNRGBA(x, y, to) + } else { + r.Set(x, y, color.Transparent) } } } diff --git a/render/text.go b/render/text.go index 91690c2..f48e02a 100644 --- a/render/text.go +++ b/render/text.go @@ -2,7 +2,6 @@ package render import ( "image" - "image/color" "golang.org/x/image/draw" "golang.org/x/image/font" @@ -17,7 +16,7 @@ func pt(p fixed.Point26_6) image.Point { } } -func RenderText(text string, scale int, col, bgCol color.Color) *image.NRGBA { +func RenderText(text string, scale int, texture, bgTex image.Image) *image.NRGBA { // @incomplete: draw with texture via Drawer.Src face := basicfont.Face7x13 stringBounds, _ := font.BoundString(face, text) @@ -26,13 +25,13 @@ func RenderText(text string, scale int, col, bgCol color.Color) *image.NRGBA { img := image.NewNRGBA(b) // fill with black bg - if (bgCol != color.NRGBA{}) { - draw.Draw(img, b, image.NewUniform(bgCol), image.Point{}, draw.Src) + if bgTex != nil { + draw.Draw(img, b, bgTex, image.Point{}, draw.Src) } d := font.Drawer{ Dst: img, - Src: image.NewUniform(col), + Src: texture, Face: face, } d.DrawString(text) diff --git a/rpc/dottir.go b/rpc/dottir.go index 1d0c157..f908805 100644 --- a/rpc/dottir.go +++ b/rpc/dottir.go @@ -35,6 +35,7 @@ type FlutTask struct { Img *image.NRGBA Offset image.Point Shuffle bool + // Effects []string // @idea shuffle, rgbsplit, randoffset, ... } type FlutAck struct{ Ok bool } diff --git a/rpc/repl.go b/rpc/repl.go index 73a49ba..1450536 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -27,9 +27,9 @@ const textMode = "TXT" // RunREPL starts reading os.Stdin for commands to apply to the given Fluter func RunREPL(f Fluter) { mode := commandMode - textSize := 4 - textCol := color.NRGBA{0xff, 0xff, 0xff, 0xff} - bgCol := color.NRGBA{} + textSize := 10 + var textCol image.Image = image.White + var bgCol image.Image = image.Transparent scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { @@ -83,22 +83,25 @@ func RunREPL(f Fluter) { f.applyTask(t) case "txt": - fmt.Printf("[rán] text mode, return via %v\n", commandMode) - mode = textMode if len(args) > 0 { if size, err := strconv.Atoi(args[0]); err == nil { textSize = size } } if len(args) > 1 { - if col, err := hex.DecodeString(args[1]); err == nil { - textCol = color.NRGBA{col[0], col[1], col[2], 0xff} - } + textCol = parseColorOrPalette(args[1]) } if len(args) > 2 { - if col, err := hex.DecodeString(args[2]); err == nil { - bgCol = color.NRGBA{col[0], col[1], col[2], 0xff} - } + bgCol = parseColorOrPalette(args[2]) + } + if len(args) < 4 { + fmt.Printf("[rán] text mode, return via %v\n", commandMode) + mode = textMode + } else { + input := strings.Join(args[3:], " ") + t := f.getTask() + t.Img = render.RenderText(input, textSize, textCol, bgCol) + f.applyTask(t) } case "img": @@ -120,3 +123,21 @@ func RunREPL(f Fluter) { } } } + +// try to parse as hex-encoded RGB color, +// alternatively treat it as palette name. If both fail, +// give image.Transparent +func parseColorOrPalette(input string) image.Image { + if col, err := hex.DecodeString(input); err == nil { + var alpha byte = 0xff + if len(col) == 4 { + alpha = col[3] + } + return image.NewUniform(color.NRGBA{col[0], col[1], col[2], alpha}) + } else if pal := render.PrideFlags[input]; len(pal) != 0 { + return &render.StripePattern{Palette: pal, Size: 13} + } else { + return &render.SineColorPattern{Luma: 0xf0, Freq: 1} + return image.Transparent + } +}