ochentiocho/main.go
2026-06-24 20:18:22 -03:00

1206 lines
25 KiB
Go

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)
}