From 40132286790a7311c7094577b794af4862ef6c61 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Thu, 10 Aug 2023 02:31:37 +0300 Subject: [PATCH] Initial commit --- .gitignore | 2 + go.mod | 3 ++ httpscreen.txt | 79 ++++++++++++++++++++++++++++++++ main.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 .gitignore create mode 100644 go.mod create mode 100644 httpscreen.txt create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f399bde --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.png +*.jpg \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8070701 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module e2http + +go 1.19 diff --git a/httpscreen.txt b/httpscreen.txt new file mode 100644 index 0000000..adb78ae --- /dev/null +++ b/httpscreen.txt @@ -0,0 +1,79 @@ +@name HttpScreen +@inputs DS:wirelink +@persist ResX ResY X Y Stage + +DS_RESET = 1048574 +DS_MODE = 1048569 +DS_CLK = 1048575 +DS_RES_X = 1048572 +DS_RES_Y = 1048573 + +function wirelink:dsClk() { + This[DS_CLK] = 1 +} + +function wirelink:dsInit(Mode, ResX, ResY) { + This[DS_RESET] = 0 + This[DS_MODE] = Mode + This:dsClk() + This[DS_RES_X] = ResX + This[DS_RES_Y] = ResY +} + +function wirelink:dsPixel(X, Y, Pixel:number) { + This[X + Y*ResY] = Pixel +} + +SERVER = "" +IMAGE = "" + +STAGE_INFO = 0 +STAGE_REQUEST = 1 +STAGE_WAIT = 2 +STAGE_RENDER = 3 +STAGE_STOP = 4 + +if (first()) { + Stage = STAGE_INFO + httpRequest(SERVER + "/image?name=" + IMAGE + "&action=resolution") + runOnHTTP(1) +} + +if (Stage == STAGE_INFO && httpClk() == 1) { + Res = httpData():explode(",") + ResX = Res[1, string]:toNumber() + ResY = Res[2, string]:toNumber() + DS:dsInit(2, ResX, ResY) + + Stage = STAGE_REQUEST +} + +interval(100) +RENDER_STRIDE = 256 + +if (Stage == STAGE_REQUEST && httpCanRequest()) { + httpRequest(SERVER + "/image?name=" + IMAGE + "&action=pixels&x=" + X + "&y=" + Y + "&count=" + RENDER_STRIDE + "&mode=2") + Stage = STAGE_WAIT + runOnHTTP(1) +} +if (Stage == STAGE_WAIT && httpClk() == 1) { + Stage = STAGE_RENDER + + Pixels = httpData():explode(",") + for (I=1,RENDER_STRIDE) { + DS:dsPixel(X+I, Y, Pixels[I, string]:toNumber()) + } + + X = X + RENDER_STRIDE + if (X >= ResX) { + X = 0 + Y++ + } + if (Y >= ResY) { + Stage = STAGE_STOP + } else { + Stage = STAGE_REQUEST + } +} else { + #print(httpData()) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..dcd266c --- /dev/null +++ b/main.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "image" + _ "image/jpeg" + _ "image/png" + "net/http" + "os" + "strconv" + "strings" +) + +type E2Image struct { + file *os.File + image image.Image + bounds image.Rectangle +} + +var images map[string]E2Image + +func getImage(name string) (E2Image, bool) { + img, ok := images[name] + if ok { + return img, true + } else { + img := E2Image{} + file, err := os.Open(name) + if err != nil { + return img, false + } + img.file = file + + m, _, err := image.Decode(file) + if err != nil { + file.Close() + return img, false + } + img.image = m + img.bounds = m.Bounds() + + return img, true + } +} + +func convertPixel(r uint32, g uint32, b uint32) (uint32, uint32, uint32) { + return (r / 0xFFFF) * 255, (g / 0xFFFF) * 255, (b / 0xFFFF) * 255 +} + +func handleImage(w http.ResponseWriter, r *http.Request) { + name := r.URL.Query().Get("name") + img, ok := getImage(name) + if !ok { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Error") + } + + action := r.URL.Query().Get("action") + switch action { + case "resolution": + fmt.Fprintf(w, "%d,%d", img.bounds.Max.X, img.bounds.Max.Y) + case "pixels": + x, _ := strconv.Atoi(r.URL.Query().Get("x")) + y, _ := strconv.Atoi(r.URL.Query().Get("y")) + count, _ := strconv.Atoi(r.URL.Query().Get("count")) + width := img.bounds.Max.X + + mode, _ := strconv.Atoi(r.URL.Query().Get("mode")) + pixels := make([]string, count) + for i := 0; i < count; i++ { + xPos := (x + i) % width + yPos := y + if x+i >= width { + yPos = y + 1 + } + + r32, g32, b32, _ := img.image.At(xPos, yPos).RGBA() + r, g, b := convertPixel(r32, g32, b32) + switch mode { + case 2: + pixels[i] = strconv.FormatUint((uint64)((r*65536)+(g*256)+b), 10) + case 3: + pixels[i] = fmt.Sprintf("%d%d%d", r, g, b) + default: + pixels[i] = strconv.FormatUint((uint64)((r*65536)+(g*256)+b), 10) + } + } + + fmt.Fprint(w, strings.Join(pixels, ",")) + } +} + +func main() { + http.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr) + for name, headers := range r.Header { + for _, value := range headers { + fmt.Fprintf(w, "%s: %s\n", name, value) + } + } + }) + + http.HandleFunc("/buffer", func(w http.ResponseWriter, r *http.Request) { + size, err := strconv.Atoi(r.URL.Query().Get("size")) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Invalid parameter") + } + + buffer := make([]byte, size) + for i := 0; i < size; i++ { + buffer[i] = 'A' + } + + w.Write(buffer) + }) + + http.HandleFunc("/image", handleImage) + + http.ListenAndServe(":1337", nil) +}