From 48f1fce93df61e02c32875aa07e016e43d63d0c4 Mon Sep 17 00:00:00 2001 From: Norwin Date: Sun, 2 Jan 2022 06:46:53 +0100 Subject: [PATCH 1/5] repl: add status,help,host cmds and don't re-apply task for local commands --- rpc/repl.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/rpc/repl.go b/rpc/repl.go index 89a35b6..5ce77cc 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -86,7 +86,7 @@ func RunREPL(f Fluter) { } } - case "address", "a": + case "host", "address", "a": if len(args) == 1 { t.Address = args[0] } @@ -131,14 +131,24 @@ func RunREPL(f Fluter) { } } + // the commands below don't affect the task, so we don't need to apply it to clients -> continue + case "metrics": f.toggleMetrics() - printTask = false + continue + + case "status": + fmt.Println(t) + continue + + case "help": + printHelp() + continue default: - printTask = false fmt.Print("[rán] unknown command. ") printHelp() + continue } if printTask { @@ -151,18 +161,18 @@ func RunREPL(f Fluter) { func printHelp() { fmt.Println(`available commands: - start start fluting - stop pause fluting + start start fluting + stop pause fluting c set number of connections per client a : set target server offset set top-left offset offset rand random offset for each draw metrics toggle bandwidth reporting (may cost some performance) - i set image - txt send text - txt [ [ []] enter interactive text mode - rgbsplit toggle RGB split effect + i set image + txt send text + txt [ [ []] enter interactive text mode + rgbsplit toggle RGB split effect o set order (l,r,t,b,shuffle)`) } From da3c05bfe457f72a075b4fc56e89dc001a0e86d4 Mon Sep 17 00:00:00 2001 From: Norwin Date: Sun, 2 Jan 2022 06:47:15 +0100 Subject: [PATCH 2/5] repl: categorize commands in help string --- rpc/repl.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/rpc/repl.go b/rpc/repl.go index 5ce77cc..66762b5 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -161,19 +161,23 @@ func RunREPL(f Fluter) { func printHelp() { fmt.Println(`available commands: + general start start fluting stop pause fluting - c set number of connections per client - a : set target server - offset set top-left offset - offset rand random offset for each draw - metrics toggle bandwidth reporting (may cost some performance) - + status print current task + content i set image txt send text txt [ [ []] enter interactive text mode + draw modes + o set order (l,r,t,b,random) + of set top-left offset + of rand random offset for each draw rgbsplit toggle RGB split effect - o set order (l,r,t,b,shuffle)`) + networking + c set number of connections per client + a : set target server + metrics toggle bandwidth reporting (may cost some performance)`) } // try to parse as hex-encoded RGB color, From 69bb57a5609321b65307b3169da1c7e25832937b Mon Sep 17 00:00:00 2001 From: Norwin Date: Sun, 2 Jan 2022 07:17:16 +0100 Subject: [PATCH 3/5] repl: add toggle start/stop shortcut --- rpc/repl.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpc/repl.go b/rpc/repl.go index 66762b5..eddeeff 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -66,6 +66,13 @@ func RunREPL(f Fluter) { case "start": t.Paused = false + case "toggle", ".": + t.Paused = !t.Paused + if t.Paused { + f.stopTask() + printTask = false + } + case "offset", "of": if len(args) == 1 && args[0] == "rand" { t.RandOffset = true From a83be545020b9395504ad6e2d7f17d247981dd5d Mon Sep 17 00:00:00 2001 From: Norwin Date: Sun, 2 Jan 2022 08:07:49 +0100 Subject: [PATCH 4/5] repl: add scale, rotate --- render/image.go | 25 ++++++++++++++++++++++--- render/text.go | 4 ++-- rpc/repl.go | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/render/image.go b/render/image.go index 1e9605a..e3dddcb 100644 --- a/render/image.go +++ b/render/image.go @@ -6,6 +6,7 @@ import ( _ "image/gif" // register gif, jpeg, png format handlers _ "image/jpeg" "image/png" + "math" "os" "golang.org/x/image/draw" @@ -63,10 +64,28 @@ func ImgColorFilter(img *image.NRGBA, from, to color.NRGBA) *image.NRGBA { return r } -func ScaleImage(img image.Image, factor int) (scaled *image.NRGBA) { +func ScaleImage(img image.Image, factorX, factorY float64, highQuality bool) (scaled *image.NRGBA) { b := img.Bounds() - scaledBounds := image.Rect(0, 0, b.Max.X*factor, b.Max.Y*factor) + newX := int(math.Ceil(factorX * float64(b.Max.X))) + newY := int(math.Ceil(factorY * float64(b.Max.Y))) + scaledBounds := image.Rect(0, 0, newX, newY) scaledImg := image.NewNRGBA(scaledBounds) - draw.NearestNeighbor.Scale(scaledImg, scaledBounds, img, b, draw.Src, nil) + scaler := draw.NearestNeighbor + if highQuality { + scaler = draw.CatmullRom + } + scaler.Scale(scaledImg, scaledBounds, img, b, draw.Src, nil) return scaledImg } + +func RotateImage90(img *image.NRGBA) (rotated *image.NRGBA) { + b := img.Bounds() + rotated = image.NewNRGBA(image.Rect(0, 0, b.Max.Y, b.Max.X)) + for x := b.Min.X; x < b.Max.X; x++ { + for y := b.Min.Y; y < b.Max.Y; y++ { + col := img.NRGBAAt(x, y) + rotated.SetNRGBA(b.Max.Y-y, x, col) + } + } + return +} diff --git a/render/text.go b/render/text.go index 84a7853..98c13f9 100644 --- a/render/text.go +++ b/render/text.go @@ -16,7 +16,7 @@ func pt(p fixed.Point26_6) image.Point { } } -func RenderText(text string, scale int, texture, bgTex image.Image) *image.NRGBA { +func RenderText(text string, scale float64, texture, bgTex image.Image) *image.NRGBA { face := basicfont.Face7x13 stringBounds, _ := font.BoundString(face, text) @@ -38,5 +38,5 @@ func RenderText(text string, scale int, texture, bgTex image.Image) *image.NRGBA img.Rect = img.Bounds().Sub(img.Bounds().Min) // scale up, as this font is quite small - return ScaleImage(img, scale) + return ScaleImage(img, scale, scale, false) } diff --git a/rpc/repl.go b/rpc/repl.go index eddeeff..cb3d5ea 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -28,7 +28,7 @@ const textMode = "txt" // RunREPL starts reading os.Stdin for commands to apply to the given Fluter func RunREPL(f Fluter) { mode := commandMode - textSize := 10 + textSize := 10.0 var textCol image.Image = image.White var bgCol image.Image = image.Transparent @@ -109,7 +109,7 @@ func RunREPL(f Fluter) { case "txt": if len(args) > 0 { if size, err := strconv.Atoi(args[0]); err == nil { - textSize = size + textSize = float64(size) } } if len(args) > 1 { @@ -138,6 +138,33 @@ func RunREPL(f Fluter) { } } + case "scale", "s": + quality := true + var facX, facY float64 + var err error + if len(args) >= 1 { + facX, err = strconv.ParseFloat(args[0], 64) + if err != nil { + fmt.Println(err) + continue + } + facY = facX + if len(args) >= 2 { + facY, err = strconv.ParseFloat(args[1], 64) + if err != nil { + fmt.Println(err) + continue + } + } + if len(args) > 2 { + quality = false + } + t.Img = render.ScaleImage(t.Img, facX, facY, quality) + } + + case "rotate", "r": + t.Img = render.RotateImage90(t.Img) + // the commands below don't affect the task, so we don't need to apply it to clients -> continue case "metrics": @@ -176,6 +203,8 @@ func printHelp() { i set image txt send text txt [ [ []] enter interactive text mode + scale [ [lofi]] scale content + rotate rotate content 90° draw modes o set order (l,r,t,b,random) of set top-left offset From 4586fdec1c885e267d435b7fd12c4c9ac0554b41 Mon Sep 17 00:00:00 2001 From: Norwin Date: Sun, 2 Jan 2022 08:18:53 +0100 Subject: [PATCH 5/5] repl: add load, store --- rpc/repl.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/rpc/repl.go b/rpc/repl.go index cb3d5ea..309b152 100644 --- a/rpc/repl.go +++ b/rpc/repl.go @@ -31,6 +31,7 @@ func RunREPL(f Fluter) { textSize := 10.0 var textCol image.Image = image.White var bgCol image.Image = image.Transparent + var taskStore = make(map[string]pixelflut.FlutTask) fmt.Print("[rán] REPL is active. ") printHelp() @@ -73,6 +74,22 @@ func RunREPL(f Fluter) { printTask = false } + case "store", "save": + printTask = false + if len(args) == 0 { + fmt.Println("must specify name") + } else { + taskStore[strings.Join(args, " ")] = t + } + continue + + case "load", "l": + if len(args) == 0 { + fmt.Println("must specify name") + } else { + t = taskStore[strings.Join(args, " ")] + } + case "offset", "of": if len(args) == 1 && args[0] == "rand" { t.RandOffset = true @@ -195,10 +212,12 @@ func RunREPL(f Fluter) { func printHelp() { fmt.Println(`available commands: - general + tasks start start fluting stop pause fluting status print current task + save store current task + load load previously stored task content i set image txt send text