From c633b3a9924355c7282805b453d9d228beb9f741 Mon Sep 17 00:00:00 2001 From: Nixietab <75538775+nixietab@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:18:22 -0300 Subject: [PATCH] real initial commit --- go.mod | 3 + main.go | 1206 +++++++++++++++++++++++++++++++++++++++++++++++++++ overlay.png | Bin 0 -> 633 bytes 3 files changed, 1209 insertions(+) create mode 100644 go.mod create mode 100644 main.go create mode 100644 overlay.png diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..296ea28 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module ochentiocho + +go 1.26.2 diff --git a/main.go b/main.go new file mode 100644 index 0000000..c6029f5 --- /dev/null +++ b/main.go @@ -0,0 +1,1206 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "image" + "image/color" + "image/draw" + "image/png" + "math" + "math/rand" + "os" +) + +var palette = map[byte][3]uint8{ + '0': {0, 0, 0}, '1': {0, 0, 128}, '2': {0, 128, 0}, + '3': {0, 128, 128}, '4': {128, 0, 0}, '5': {128, 0, 128}, + '6': {128, 128, 0}, '7': {192, 192, 192}, '8': {128, 128, 128}, + '9': {0, 0, 255}, 'a': {0, 255, 0}, 'b': {0, 255, 255}, + 'c': {255, 0, 0}, 'd': {255, 0, 255}, 'e': {255, 255, 0}, + 'f': {255, 255, 255}, +} + +var ( + bright = []byte("9abcdef") + dark = []byte("012345") + mid = []byte("6789abcd") + all = []byte("0123456789abcdef") +) + +func u4(n int) byte { + return "0123456789abcdef"[n&0xF] +} + +func randColor(pool []byte) byte { + if pool == nil { + pool = all + } + return pool[rand.Intn(len(pool))] +} + +func hexToRGB(c byte) [3]uint8 { + if v, ok := palette[c]; ok { + return v + } + return [3]uint8{0, 0, 0} +} + +func effToPixels(eff map[int]string) [][]color.RGBA { + pixels := make([][]color.RGBA, 31) + for i := 0; i < 31; i++ { + row := make([]color.RGBA, 88) + rowStr := eff[i+1] + for j := 0; j < 88; j++ { + if j < len(rowStr) { + rgb := hexToRGB(rowStr[j]) + row[j] = color.RGBA{rgb[0], rgb[1], rgb[2], 255} + } else { + row[j] = color.RGBA{0, 0, 0, 255} + } + } + pixels[i] = row + } + return pixels +} + +var sin = []byte("01122334455666777888889999999999998888777666554433221100") + +var sinAltInt = []int{ + 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 9, 9, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, +} + +func arrayRandomize(ref []byte, colorSet string) []byte { + mapping := make(map[byte]byte) + hexChars := []byte("0123456789abcdef") + if colorSet != "" { + colors := []byte{} + for i := 0; i < len(colorSet); i++ { + if colorSet[i] != ' ' { + colors = append(colors, colorSet[i]) + } + } + for _, h := range hexChars { + mapping[h] = colors[rand.Intn(len(colors))] + } + } else { + for _, h := range hexChars { + mapping[h] = u4(rand.Intn(16)) + } + } + result := make([]byte, len(ref)) + for i, x := range ref { + if v, ok := mapping[x]; ok { + result[i] = v + } else { + result[i] = x + } + } + return result +} + +func effectSinRand() map[int]string { + eff := make(map[int]string) + s := []string{"f a", "a b d", "a b", "a f", "c d", "e 5", "b c f"} + meow := arrayRandomize(sin, s[rand.Intn(len(s))]) + a := 0 + for i := 1; i < 32; i += 2 { + eff[i] = "" + eff[i+1] = "" + for j := 1; j < 45; j++ { + idx := (a * 2) % len(meow) + l := meow[idx] + eff[i] += string([]byte{l, l}) + eff[i+1] += string([]byte{l, l}) + a++ + if a >= len(meow) { + a = 0 + } + } + } + return eff +} + +func effectSinRandWorse() map[int]string { + eff := make(map[int]string) + length := rand.Intn(99) + meow := make([]byte, length) + for i := range meow { + meow[i] = '0' + } + meow = arrayRandomize(meow, "a b c d e f") + a := 0 + for i := 1; i < 32; i += 2 { + eff[i+1] = "0" + eff[i] = "" + for j := 1; j < 45; j++ { + var idx int + if len(meow) > 0 { + idx = (a * 2) % len(meow) + } + var l byte = '0' + if len(meow) > 0 { + l = meow[idx] + } + eff[i] += string([]byte{l, l}) + eff[i+1] += string([]byte{l, l}) + a++ + if a >= length { + a = 0 + } + } + } + return eff +} + +func effectSin2() map[int]string { + eff := make(map[int]string) + c := []string{"a f", "e 5", "d c", "d b"} + randa := c[rand.Intn(len(c))] + randb := c[rand.Intn(len(c))] + randc := c[rand.Intn(len(c))] + randd := c[rand.Intn(len(c))] + rd := []byte{randd[0], randd[2]} + ra := []byte{randa[0], randa[2]} + rb := []byte{randb[0], randb[2]} + rc := []byte{randc[0], randc[2]} + for i := 1; i < 32; i++ { + eff[i] = "" + for j := 1; j < 89; j++ { + x := 15 + if j-1 < len(sinAltInt) { + x = sinAltInt[j-1] + 15 + } + switch { + case x == i-10: + eff[i] += string(rd[0]) + case x == i-9: + eff[i] += string(rd[1]) + case x == i-8: + eff[i] += string(rd[0]) + case x == i: + eff[i] += string(ra[0]) + case x == i+1: + eff[i] += string(ra[1]) + case x == i+2: + eff[i] += string(ra[0]) + case x == i+10: + eff[i] += string(rb[0]) + case x == i+11: + eff[i] += string(rb[1]) + case x == i+12: + eff[i] += string(rb[0]) + case x == i+20: + eff[i] += string(rc[0]) + case x == i+21: + eff[i] += string(rc[1]) + case x == i+22: + eff[i] += string(rc[0]) + default: + eff[i] += "0" + } + } + } + return eff +} + +func effectRand() map[int]string { + eff := make(map[int]string) + for i := 1; i < 32; i += 2 { + eff[i] = "" + eff[i+1] = "" + for j := 1; j < 45; j++ { + a := u4(rand.Intn(5) + 10) + eff[i] += string([]byte{a, a}) + eff[i+1] += string([]byte{a, a}) + } + } + return eff +} + +func effectSpeccy() map[int]string { + eff := make(map[int]string) + b := rand.Intn(3) + 3 + for i := 1; i < 32; i++ { + eff[i] = "" + for j := 1; j < 11; j++ { + eff[i] += "0" + } + a := 10 + i + j := 11 + for ; j < 89; j++ { + if a == j { + break + } + eff[i] += "0" + } + for ; j < 89; j++ { + if i < 6 && j < 40 { + eff[i] += "0" + } else { + eff[i] += string(u4(((j - a) % b) + 10)) + } + } + } + return eff +} + +func effectSpeccy2x() map[int]string { + eff := make(map[int]string) + b := rand.Intn(3) + 3 + for i := 1; i < 32; i++ { + eff[i] = "" + for j := 1; j < 11; j++ { + eff[i] += "0" + } + a := 10 + i + j := 11 + for ; j < 89; j++ { + if a == j { + break + } + eff[i] += "0" + } + for ; j < 89; j += 2 { + if i < 6 && j < 40 { + eff[i] += "00" + } else { + c := u4(((j - a) % b) + 10) + eff[i] += string([]byte{c, c}) + } + } + } + return eff +} + +func effectSpeccy2xPride() map[int]string { + eff := make(map[int]string) + c := []string{"e d a 2 6 b", "5 9 5 c", "0 e 9 2", "0e cc 5b"} + bStr := c[rand.Intn(len(c))] + b := []string{} + for i := 0; i < len(bStr); { + if bStr[i] == ' ' { + i++ + continue + } + if i+1 < len(bStr) && bStr[i+1] != ' ' { + b = append(b, bStr[i:i+2]) + i += 2 + } else { + b = append(b, bStr[i:i+1]) + i++ + } + } + w := []int{4, 6, 8, 10, 12, 16, 24} + width := w[rand.Intn(len(w))] + for i := 1; i < 32; i++ { + eff[i] = "" + for j := 1; j < 11; j++ { + eff[i] += "0" + } + a := 10 + i + j := 11 + for ; j < 89; j++ { + if a == j { + break + } + eff[i] += "0" + } + for ; j < 89; j += 2 { + if i < 6 && j < 40 { + eff[i] += "00" + } else { + idx := ((i - j) / width) % len(b) + if idx < 0 { + idx = -idx + } + d := b[idx] + if len(d) == 2 { + eff[i] += d + } else { + eff[i] += d + d + } + } + } + } + return eff +} + +func effectCheckerboard() map[int]string { + eff := make(map[int]string) + s := []byte("abcdef5") + c := s[rand.Intn(len(s))] + for i := 1; i < 32; i++ { + eff[i] = "" + if (i%4)/2 == 0 { + eff[i] += "00" + } + for j := 1; j < 89; j++ { + if j%2 == 0 { + eff[i] += "00" + } else { + eff[i] += string([]byte{c, c}) + } + } + } + return eff +} + +func effectHorizontalStripes() map[int]string { + eff := make(map[int]string) + colors := make([]byte, rand.Intn(5)+2) + for i := range colors { + colors[i] = randColor(bright) + } + thickness := rand.Intn(4) + 1 + for i := 1; i < 32; i++ { + c := colors[(i/thickness)%len(colors)] + eff[i] = string(bytes.Repeat([]byte{c}, 88)) + } + return eff +} + +func effectVerticalStripes() map[int]string { + eff := make(map[int]string) + colors := make([]byte, rand.Intn(7)+2) + for i := range colors { + colors[i] = randColor(bright) + } + thickness := rand.Intn(7) + 2 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + row[j-1] = colors[(j/thickness)%len(colors)] + } + eff[i] = string(row) + } + return eff +} + +func effectDiagonalStripes() map[int]string { + eff := make(map[int]string) + colors := make([]byte, rand.Intn(4)+2) + for i := range colors { + colors[i] = randColor(bright) + } + slope := rand.Intn(4) + 1 + div := rand.Intn(6) + 3 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + idx := ((i + j*slope) / div) % len(colors) + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectGradientHorizontal() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if j < 44 { + if rand.Float64() > (float64(j) / 44.0) { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } else { + if rand.Float64() > (float64(j-44) / 44.0) { + row[j-1] = c2 + } else { + row[j-1] = c1 + } + } + } + eff[i] = string(row) + } + return eff +} + +func effectGradientVertical() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + t := float64(i-1) / 30.0 + for j := 1; j < 89; j++ { + if rand.Float64() > t { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectPlasma() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 4) + for i := range colors { + colors[i] = randColor(bright) + } + scale1 := rand.Float64()*0.3 + 0.1 + scale2 := rand.Float64()*0.3 + 0.1 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + v := math.Sin(float64(i)*scale1) + math.Cos(float64(j)*scale2) + math.Sin(float64(i+j)*0.1) + idx := int((v+2)*float64(len(colors))/4.0) % len(colors) + if idx < 0 { + idx = -idx + } + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectNoise() map[int]string { + eff := make(map[int]string) + pool := append([]byte{}, bright...) + pool = append(pool, mid...) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + row[j-1] = randColor(pool) + } + eff[i] = string(row) + } + return eff +} + +func effectDitheredNoise() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + threshold := rand.Float64()*0.4 + 0.3 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if rand.Float64() > threshold { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectScanlines() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if i%2 == 0 { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectCrosshatch() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + period := rand.Intn(6) + 3 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if i%period == 0 || j%period == 0 { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectZigzag() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 3) + for i := range colors { + colors[i] = randColor(bright) + } + period := rand.Intn(7) + 4 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + z := (i + (j % (period * 2))) / period + row[j-1] = colors[z%len(colors)] + } + eff[i] = string(row) + } + return eff +} + +func effectRainbow() map[int]string { + eff := make(map[int]string) + rainbow := []byte("ce a9d5b") + thickness := rand.Intn(4) + 2 + for i := 1; i < 32; i++ { + c := rainbow[(i/thickness)%len(rainbow)] + eff[i] = string(bytes.Repeat([]byte{c}, 88)) + } + return eff +} + +func effectRainbowVertical() map[int]string { + eff := make(map[int]string) + rainbow := []byte("ce a9d5b") + thickness := rand.Intn(9) + 4 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + row[j-1] = rainbow[(j/thickness)%len(rainbow)] + } + eff[i] = string(row) + } + return eff +} + +func effectWaveHorizontal() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + freq := rand.Float64()*0.3 + 0.1 + amp := rand.Intn(6) + 3 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + waveCenter := 15 + int(float64(amp)*math.Sin(float64(i)*freq)) + for j := 1; j < 89; j++ { + dist := abs(j - waveCenter) + if dist < 3 { + row[j-1] = c1 + } else if dist < 6 { + row[j-1] = c2 + } else { + row[j-1] = '0' + } + } + eff[i] = string(row) + } + return eff +} + +func effectWaveVertical() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 4) + for i := range colors { + colors[i] = randColor(bright) + } + freq := rand.Float64()*0.2 + 0.1 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + v := int(2*math.Sin(float64(j)*freq) + 2) + row[j-1] = colors[v%len(colors)] + } + eff[i] = string(row) + } + return eff +} + +func effectCircles() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 5) + for i := range colors { + colors[i] = randColor(bright) + } + cx, cy := 44.0, 15.0 + div := rand.Float64()*3.0 + 3.0 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + dist := math.Sqrt(math.Pow(float64(j)-cx, 2) + math.Pow(float64(i)-cy, 2)) + idx := int(dist/div) % len(colors) + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectRadialGradient() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + cx, cy := 44.0, 15.0 + maxDist := math.Sqrt(44*44 + 15*15) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + dist := math.Sqrt(math.Pow(float64(j)-cx, 2) + math.Pow(float64(i)-cy, 2)) + t := dist / maxDist + if rand.Float64() > t { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectDiamond() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 3) + for i := range colors { + colors[i] = randColor(bright) + } + size := rand.Intn(7) + 4 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + d := (abs(i-16) + abs(j-44)) / size + row[j-1] = colors[d%len(colors)] + } + eff[i] = string(row) + } + return eff +} + +func effectTriangles() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 3) + for i := range colors { + colors[i] = randColor(bright) + } + period := rand.Intn(9) + 6 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + t := float64(j%period) / float64(period) + if t < 0.33 { + row[j-1] = colors[0] + } else if t < 0.66 { + row[j-1] = colors[1] + } else { + row[j-1] = colors[2] + } + } + eff[i] = string(row) + } + return eff +} + +func effectBorder() map[int]string { + eff := make(map[int]string) + border := randColor(bright) + fill := randColor(dark) + bw := rand.Intn(4) + 2 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if i <= bw || i > 31-bw || j <= bw || j > 88-bw { + row[j-1] = border + } else { + row[j-1] = fill + } + } + eff[i] = string(row) + } + return eff +} + +func effectDots() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + spacing := rand.Intn(6) + 5 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if (i%spacing) == (spacing/2) && (j%spacing) == (spacing/2) { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectMaze() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + block := rand.Intn(7) + 4 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + bx := (j / block) % 2 + by := (i / block) % 2 + if bx^by == 1 { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectInterference() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 3) + for i := range colors { + colors[i] = randColor(bright) + } + f1 := rand.Float64()*0.2 + 0.1 + f2 := rand.Float64()*0.2 + 0.1 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + v := math.Sin(float64(i)*f1) * math.Sin(float64(j)*f2) + idx := 0 + if v > 0.3 { + idx = 0 + } else if v > -0.3 { + idx = 1 + } else { + idx = 2 + } + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectVoronoi() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 4) + for i := range colors { + colors[i] = randColor(bright) + } + points := make([][2]int, 4) + for i := range points { + points[i] = [2]int{rand.Intn(69) + 10, rand.Intn(22) + 5} + } + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + minDist := 1<<30 + nearest := 0 + for idx, p := range points { + d := (j-p[0])*(j-p[0]) + (i-p[1])*(i-p[1]) + if d < minDist { + minDist = d + nearest = idx + } + } + row[j-1] = colors[nearest] + } + eff[i] = string(row) + } + return eff +} + +func effectSpiral() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 4) + for i := range colors { + colors[i] = randColor(bright) + } + cx, cy := 44.0, 15.0 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + dx := float64(j) - cx + dy := float64(i) - cy + angle := math.Atan2(dy, dx) + dist := math.Sqrt(dx*dx + dy*dy) + spiral := (dist + angle*5) / 8 + idx := int(spiral) % len(colors) + if idx < 0 { + idx = -idx + } + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectTartan() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + c3 := randColor(bright) + hPeriod := rand.Intn(9) + 6 + vPeriod := rand.Intn(9) + 6 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + h := (i/(hPeriod/2))%2 == 0 + v := (j/(vPeriod/2))%2 == 0 + if h && v { + row[j-1] = c3 + } else if h || v { + row[j-1] = c2 + } else { + row[j-1] = c1 + } + } + eff[i] = string(row) + } + return eff +} + +func effectBricks() map[int]string { + eff := make(map[int]string) + brick := randColor(bright) + mortar := randColor(dark) + h := rand.Intn(4) + 3 + w := rand.Intn(9) + 8 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + offset := (i / h) % 2 * (w / 2) + for j := 1; j < 89; j++ { + bx := (j + offset) % w + by := i % h + if bx == 0 || by == 0 { + row[j-1] = mortar + } else { + row[j-1] = brick + } + } + eff[i] = string(row) + } + return eff +} + +func effectRipple() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 4) + for i := range colors { + colors[i] = randColor(bright) + } + cx, cy := 44.0, 15.0 + div := rand.Float64()*3.0 + 2.0 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + dist := math.Sqrt(math.Pow(float64(j)-cx, 2) + math.Pow(float64(i)-cy, 2)) + idx := int(dist/div) % len(colors) + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectHeatMap() map[int]string { + eff := make(map[int]string) + colors := []byte("046ec") + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + v := (float64(i) / 31.0) * (float64(j) / 88.0) + idx := int(v*float64(len(colors))) % len(colors) + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectPixelSort() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 5) + for i := range colors { + colors[i] = randColor(bright) + } + for i := 1; i < 32; i++ { + row := make([]byte, 0, 88) + band := rand.Intn(9) + 4 + pos := 0 + for pos < 88 { + c := colors[rand.Intn(len(colors))] + w := rand.Intn(band-1) + 2 + if pos+w > 88 { + w = 88 - pos + } + for k := 0; k < w; k++ { + row = append(row, c) + } + pos += w + } + eff[i] = string(row) + } + return eff +} + +func effectLissajous() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + a := rand.Intn(4) + 2 + b := rand.Intn(4) + 2 + delta := rand.Float64() * math.Pi + curve := make(map[[2]int]bool) + for t := 0; t < 1000; t++ { + tt := float64(t) * 0.01 + x := int(44 + 35*math.Sin(float64(a)*tt+delta)) + y := int(15 + 10*math.Sin(float64(b)*tt)) + if y >= 1 && y <= 31 && x >= 1 && x <= 88 { + curve[[2]int{x, y}] = true + } + } + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if curve[[2]int{j, i}] { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectTextured() map[int]string { + eff := make(map[int]string) + base := randColor(dark) + accent := randColor(bright) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if rand.Float64() < 0.15 { + row[j-1] = accent + } else { + row[j-1] = base + } + } + eff[i] = string(row) + } + return eff +} + +func effectHalftone() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + dist := math.Sqrt(math.Pow(float64(j)-44, 2) + math.Pow(float64(i)-15, 2)) + threshold := dist / 50.0 + if rand.Float64() > threshold { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectPinstripe() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + if j%2 == 0 { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectSunburst() map[int]string { + eff := make(map[int]string) + colors := make([]byte, 6) + for i := range colors { + colors[i] = randColor(bright) + } + cx, cy := 44.0, 15.0 + rays := rand.Intn(11) + 6 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + angle := math.Atan2(float64(i)-cy, float64(j)-cx) + idx := int((angle+math.Pi)/(2*math.Pi)*float64(rays)) % len(colors) + if idx < 0 { + idx = -idx + } + row[j-1] = colors[idx] + } + eff[i] = string(row) + } + return eff +} + +func effectBayer() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(dark) + bayer := [4][4]int{ + {0, 8, 2, 10}, + {12, 4, 14, 6}, + {3, 11, 1, 9}, + {15, 7, 13, 5}, + } + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + threshold := float64(bayer[(i-1)%4][(j-1)%4]) / 16.0 + if threshold > 0.5 { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } + eff[i] = string(row) + } + return eff +} + +func effectWoven() map[int]string { + eff := make(map[int]string) + c1 := randColor(bright) + c2 := randColor(bright) + c3 := randColor(dark) + period := rand.Intn(5) + 4 + for i := 1; i < 32; i++ { + row := make([]byte, 88) + for j := 1; j < 89; j++ { + h := (i/period)%2 == 0 + v := (j/period)%2 == 0 + if h == v { + if h { + row[j-1] = c1 + } else { + row[j-1] = c2 + } + } else { + row[j-1] = c3 + } + } + eff[i] = string(row) + } + return eff +} + +var effects = []func() map[int]string{ + effectSinRand, + effectSinRandWorse, + effectSin2, effectSin2, effectSin2, + effectRand, + effectSpeccy2x, + effectSpeccy2xPride, effectSpeccy2xPride, + effectCheckerboard, + effectHorizontalStripes, effectVerticalStripes, effectDiagonalStripes, + effectGradientHorizontal, effectGradientVertical, effectPlasma, + effectNoise, effectDitheredNoise, effectScanlines, effectCrosshatch, + effectZigzag, effectRainbow, effectRainbowVertical, + effectWaveHorizontal, effectWaveVertical, effectCircles, + effectRadialGradient, effectDiamond, effectTriangles, effectBorder, + effectDots, effectMaze, effectInterference, effectVoronoi, + effectSpiral, effectTartan, effectBricks, effectRipple, + effectHeatMap, effectPixelSort, effectLissajous, effectTextured, + effectHalftone, effectPinstripe, effectSunburst, effectBayer, effectWoven, +} + +func compositeWithOverlay(basePixels [][]color.RGBA, overlayPath string) (image.Image, error) { + base := image.NewRGBA(image.Rect(0, 0, 88, 31)) + for y, row := range basePixels { + for x, c := range row { + base.SetRGBA(x, y, c) + } + } + overlayFile, err := os.Open(overlayPath) + if err != nil { + return nil, err + } + defer overlayFile.Close() + overlay, err := png.Decode(overlayFile) + if err != nil { + return nil, err + } + if overlay.Bounds().Dx() != 88 || overlay.Bounds().Dy() != 31 { + resized := image.NewRGBA(image.Rect(0, 0, 88, 31)) + for y := 0; y < 31; y++ { + for x := 0; x < 88; x++ { + sx := x * overlay.Bounds().Dx() / 88 + sy := y * overlay.Bounds().Dy() / 31 + resized.Set(x, y, overlay.At(sx+overlay.Bounds().Min.X, sy+overlay.Bounds().Min.Y)) + } + } + overlay = resized + } + result := image.NewRGBA(image.Rect(0, 0, 88, 31)) + draw.Draw(result, result.Bounds(), base, image.Point{}, draw.Src) + draw.Draw(result, result.Bounds(), overlay, image.Point{}, draw.Over) + return result, nil +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} + +func main() { + var overlayPath, outputPath string + flag.StringVar(&overlayPath, "overlay", "overlay.png", "Absolute path to the overlay PNG file") + flag.StringVar(&outputPath, "output", "button.png", "Absolute path for the output PNG file") + flag.Parse() + + effectFunc := effects[rand.Intn(len(effects))] + eff := effectFunc() + pixels := effToPixels(eff) + result, err := compositeWithOverlay(pixels, overlayPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + out, err := os.Create(outputPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + defer out.Close() + if err := png.Encode(out, result); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + fmt.Printf("Generated %s\n", outputPath) +} diff --git a/overlay.png b/overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..d388ae8b2349347214457a0035b2c135d242e4fc GIT binary patch literal 633 zcmV-<0*3vGP)Yn_SECY-yuaRRnN$-&|gr&1GE#O$vh6rL7H4YUf>o5TAP=%L>iG zia)yALx2GiBn8P=?Suy>Ob18Xf$q{ap7^wHfXo4w`mHgfe0%o-$S(|-OO}G7VCw{U z+IipO;!A)%{c7>76=40}3>c~wSAb_QT00EbdXHA01vr}TpI0!J1w4z=l9ObBLiI=t z*LMrxOo`Ckf^?VjYm>wJ2C`6prNMc0Q3EV(UR>WW$y9^2iIrA?wd|vAL5jx$#!1nE zN-jd%cp`wczApi|4uW$Ml8eZ!V5{#8iRjVYmTO({Hcf-f`O1t6#uds{@+AOshXqaJ zGAr2X`!awdn}+5tID1F+*gBzk97}7yQMpKw2