From 4f2fa7b8d6811ac0aaa17bb3744d959d30d11f55 Mon Sep 17 00:00:00 2001 From: Ed Date: Thu, 26 Feb 2026 05:38:37 +0000 Subject: [PATCH] feat: daily wallpaper generator with 12 randomized algorithms Picks 6 of 12 each run, all params randomized. Pixel 8 (1080x2400). Algorithms: ghost, aurora, data-rain, fractal-burn, void-signal, neon-decay, static-portrait, circuit-dream, plasma-tear, bit-cascade, deep-scan, entropy-wave. --- .gitignore | 2 + daily.go | 602 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 604 insertions(+) create mode 100644 .gitignore create mode 100644 daily.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2fd0a7e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +daily-preview/ +daily-*/ diff --git a/daily.go b/daily.go new file mode 100644 index 0000000..69bd25f --- /dev/null +++ b/daily.go @@ -0,0 +1,602 @@ +// Daily Glitch Wallpaper Generator +// Generates 6 unique glitch-inspired wallpapers at Pixel 8 resolution (1080x2400) +// Each run produces different art via randomized parameters and algorithm selection. +// +// Usage: go run daily.go [output-dir] + +package main + +import ( + "fmt" + "image" + "image/color" + "image/png" + "math" + "math/rand" + "os" + "path/filepath" + "time" +) + +const ( + W = 1080 + H = 2400 +) + +func main() { + rand.Seed(time.Now().UnixNano()) + + outDir := "daily-output" + if len(os.Args) > 1 { + outDir = os.Args[1] + } + os.MkdirAll(outDir, 0755) + + // Pool of generators — pick 6 unique ones (or repeat with different params if pool < 6) + type Generator struct { + Name string + Draw func(img *image.RGBA, w, h int) + } + + generators := []Generator{ + {"ghost-in-the-machine", drawGhost}, + {"pixel-aurora", drawAurora}, + {"data-rain", drawDataRain}, + {"fractal-burn", drawFractalBurn}, + {"void-signal", drawVoidSignal}, + {"neon-decay", drawNeonDecay}, + {"static-portrait", drawStaticPortrait}, + {"circuit-dream", drawCircuitDream}, + {"plasma-tear", drawPlasmaTear}, + {"bit-cascade", drawBitCascade}, + {"deep-scan", drawDeepScan}, + {"entropy-wave", drawEntropyWave}, + } + + // Shuffle and pick 6 + rand.Shuffle(len(generators), func(i, j int) { + generators[i], generators[j] = generators[j], generators[i] + }) + + for i := 0; i < 6; i++ { + gen := generators[i] + img := image.NewRGBA(image.Rect(0, 0, W, H)) + gen.Draw(img, W, H) + + name := fmt.Sprintf("%02d-%s.png", i+1, gen.Name) + path := filepath.Join(outDir, name) + f, err := os.Create(path) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + continue + } + png.Encode(f, img) + f.Close() + fmt.Printf("āœ“ %s\n", path) + } + fmt.Println("\nšŸŽŖ Done!") +} + +func clamp(v float64) uint8 { + if v < 0 { + return 0 + } + if v > 255 { + return 255 + } + return uint8(v) +} + +func lerpColor(a, b color.RGBA, t float64) color.RGBA { + return color.RGBA{ + clamp(float64(a.R)*(1-t) + float64(b.R)*t), + clamp(float64(a.G)*(1-t) + float64(b.G)*t), + clamp(float64(a.B)*(1-t) + float64(b.B)*t), + 255, + } +} + +func fillBg(img *image.RGBA, w, h int, top, bot color.RGBA) { + for y := 0; y < h; y++ { + t := float64(y) / float64(h) + c := lerpColor(top, bot, t) + for x := 0; x < w; x++ { + img.SetRGBA(x, y, c) + } + } +} + +func addScanlines(img *image.RGBA, w, h int, intensity float64) { + for y := 0; y < h; y += 2 + rand.Intn(3) { + a := intensity * (0.5 + rand.Float64()*0.5) + for x := 0; x < w; x++ { + c := img.RGBAAt(x, y) + c.R = clamp(float64(c.R) * (1 - a)) + c.G = clamp(float64(c.G) * (1 - a)) + c.B = clamp(float64(c.B) * (1 - a)) + img.SetRGBA(x, y, c) + } + } +} + +func addGlitchBars(img *image.RGBA, w, h int, count int) { + for i := 0; i < count; i++ { + barY := rand.Intn(h) + barH := 1 + rand.Intn(4) + shift := rand.Intn(30) - 15 + tint := []color.RGBA{ + {255, 0, 80, 255}, {0, 255, 200, 255}, {200, 0, 255, 255}, {255, 200, 0, 255}, + }[rand.Intn(4)] + a := 0.1 + rand.Float64()*0.25 + + for dy := 0; dy < barH; dy++ { + yy := barY + dy + if yy >= h { + break + } + for x := 0; x < w; x++ { + sx := x + shift + if sx < 0 || sx >= w { + continue + } + c := img.RGBAAt(sx, yy) + c.R = clamp(float64(c.R)*(1-a) + float64(tint.R)*a) + c.G = clamp(float64(c.G)*(1-a) + float64(tint.G)*a) + c.B = clamp(float64(c.B)*(1-a) + float64(tint.B)*a) + img.SetRGBA(x, yy, c) + } + } + } +} + +// === GENERATORS === + +func drawGhost(img *image.RGBA, w, h int) { + fillBg(img, w, h, color.RGBA{3, 3, 12, 255}, color.RGBA{10, 8, 30, 255}) + cx := float64(w) / 2 + startY := float64(h) * 0.12 + fh := float64(h) * 0.70 + n := w * 120 + for i := 0; i < n; i++ { + t := float64(i) / float64(n) + sway := math.Sin(t*22+rand.Float64()*0.5) * float64(w) * (0.08 - t*0.05) + spread := math.Sin(t*math.Pi) * float64(w) * 0.12 + px := int(cx + sway + (rand.Float64()-0.5)*spread*2) + py := int(startY + t*fh + (rand.Float64()-0.5)*4) + if px < 0 || px >= w || py < 0 || py >= h { + continue + } + alpha := (1 - t) * 0.85 + if rand.Float64() > 0.96 { + for dx := -8; dx < 15+rand.Intn(w/12); dx++ { + sx := px + dx + if sx >= 0 && sx < w { + img.SetRGBA(sx, py, color.RGBA{clamp(255 * alpha), 0, clamp(100 * alpha), 255}) + } + } + } else { + img.SetRGBA(px, py, color.RGBA{clamp(150 * alpha), clamp(200 * alpha), clamp(255 * alpha), 255}) + } + } + addScanlines(img, w, h, 0.04) + addGlitchBars(img, w, h, 6) +} + +func drawAurora(img *image.RGBA, w, h int) { + phase1 := rand.Float64() * math.Pi * 2 + phase2 := rand.Float64() * math.Pi * 2 + freq := 0.003 + rand.Float64()*0.004 + + fillBg(img, w, h, color.RGBA{2, 2, 15, 255}, color.RGBA{5, 3, 20, 255}) + for y := 0; y < h; y++ { + fy := float64(y) / float64(h) + // Aurora bands in the upper portion + bandIntensity := math.Exp(-math.Pow((fy-0.3)/0.25, 2)) + for x := 0; x < w; x++ { + fx := float64(x) + wave1 := math.Sin(fx*freq+phase1+fy*3) * 0.5 + wave2 := math.Cos(fx*freq*1.7+phase2+fy*2) * 0.3 + v := (wave1 + wave2 + 0.5) * bandIntensity + + tear := 0.0 + if math.Sin(fy*80+fx*0.01) > 0.97 { + tear = 0.4 + } + + r := clamp(v*80 + tear*200) + g := clamp(v * 255) + b := clamp(v*180 + tear*100) + + c := img.RGBAAt(x, y) + c.R = clamp(float64(c.R) + float64(r)) + c.G = clamp(float64(c.G) + float64(g)) + c.B = clamp(float64(c.B) + float64(b)) + img.SetRGBA(x, y, c) + } + } + // Stars + for i := 0; i < 400; i++ { + px, py := rand.Intn(w), rand.Intn(h/2) + b := uint8(100 + rand.Intn(155)) + img.SetRGBA(px, py, color.RGBA{b, b, b, 255}) + } + addGlitchBars(img, w, h, 4) +} + +func drawDataRain(img *image.RGBA, w, h int) { + baseHue := rand.Float64() // randomize color each run + fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{5, 5, 10, 255}) + cols := w / 8 + for c := 0; c < cols; c++ { + x := c*8 + rand.Intn(4) + speed := 3 + rand.Intn(8) + startOff := rand.Intn(h) + length := 40 + rand.Intn(120) + for i := 0; i < length; i++ { + y := (startOff + i*speed) % h + t := float64(i) / float64(length) + brightness := (1 - t) * 0.9 + + // HSV-ish color from baseHue + r := clamp(math.Sin(baseHue*math.Pi*2)*100*brightness + 50*brightness) + g := clamp(math.Sin((baseHue+0.33)*math.Pi*2)*100*brightness + 200*brightness) + b := clamp(math.Sin((baseHue+0.66)*math.Pi*2)*100*brightness + 80*brightness) + + for dx := 0; dx < 3; dx++ { + if x+dx < w { + img.SetRGBA(x+dx, y, color.RGBA{r, g, b, 255}) + } + } + } + } + addScanlines(img, w, h, 0.06) + addGlitchBars(img, w, h, 10) +} + +func drawFractalBurn(img *image.RGBA, w, h int) { + cx := float64(w)/2 + rand.Float64()*100 - 50 + cy := float64(h)/2 + rand.Float64()*200 - 100 + maxIter := 80 + rand.Intn(40) + zoom := 200.0 + rand.Float64()*200 + + palette := []color.RGBA{ + {20, 0, 40, 255}, {80, 0, 120, 255}, {200, 50, 50, 255}, + {255, 150, 0, 255}, {255, 255, 100, 255}, {255, 255, 255, 255}, + } + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + zr := (float64(x) - cx) / zoom + zi := (float64(y) - cy) / zoom + cr, ci := zr, zi + iter := 0 + for ; iter < maxIter; iter++ { + zr2, zi2 := zr*zr, zi*zi + if zr2+zi2 > 4 { + break + } + zr, zi = zr2-zi2+cr, 2*zr*zi+ci + } + t := float64(iter) / float64(maxIter) + idx := t * float64(len(palette)-1) + i1 := int(idx) + if i1 >= len(palette)-1 { + i1 = len(palette) - 2 + } + frac := idx - float64(i1) + + // Burn effect — occasional pixel corruption + if (x*131+y*97+iter*3)%200 < 3 { + img.SetRGBA(x, y, color.RGBA{255, 255, 255, 255}) + } else { + img.SetRGBA(x, y, lerpColor(palette[i1], palette[i1+1], frac)) + } + } + } + addGlitchBars(img, w, h, 8) +} + +func drawVoidSignal(img *image.RGBA, w, h int) { + fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{0, 0, 5, 255}) + ringCx := float64(w)/2 + rand.Float64()*60 - 30 + ringCy := float64(h)*0.4 + rand.Float64()*100 + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + dist := math.Hypot(float64(x)-ringCx, float64(y)-ringCy) + ring := math.Sin(dist*0.04) * 0.5 * math.Exp(-dist*0.001) + noise := float64((x*9871+y*6563)%256) / 256.0 + + v := ring*0.8 + noise*0.05 + + // Color: deep teal to white + r := clamp(v * 150) + g := clamp(v * 255) + b := clamp(v * 280) + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + addScanlines(img, w, h, 0.08) + addGlitchBars(img, w, h, 12) +} + +func drawNeonDecay(img *image.RGBA, w, h int) { + neonColors := []color.RGBA{ + {255, 0, 110, 255}, {0, 255, 200, 255}, {130, 50, 255, 255}, + {255, 200, 0, 255}, {0, 150, 255, 255}, + } + pick := neonColors[rand.Intn(len(neonColors))] + pick2 := neonColors[rand.Intn(len(neonColors))] + + fillBg(img, w, h, color.RGBA{8, 5, 15, 255}, color.RGBA{15, 8, 25, 255}) + + // Neon lines that decay + for l := 0; l < 30+rand.Intn(20); l++ { + y := rand.Intn(h) + thickness := 2 + rand.Intn(6) + c := pick + if rand.Float64() > 0.5 { + c = pick2 + } + decayStart := rand.Intn(w / 2) + for x := 0; x < w; x++ { + alpha := 1.0 + if x > decayStart { + decay := float64(x-decayStart) / float64(w-decayStart) + alpha = 1 - decay + // Chunk decay — blocks disappear + if ((x/8)*17+l*31)%10 < int(decay*10) { + continue + } + } + for dy := 0; dy < thickness; dy++ { + yy := y + dy + if yy < h { + img.SetRGBA(x, yy, color.RGBA{ + clamp(float64(c.R) * alpha), + clamp(float64(c.G) * alpha), + clamp(float64(c.B) * alpha), + 255, + }) + } + } + } + } + addScanlines(img, w, h, 0.03) +} + +func drawStaticPortrait(img *image.RGBA, w, h int) { + // TV static with a silhouette carved out + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + v := uint8(rand.Intn(60)) + img.SetRGBA(x, y, color.RGBA{v, v, v, 255}) + } + } + // Silhouette — oval head + body + headCx, headCy := float64(w)/2, float64(h)*0.28 + headRx, headRy := float64(w)*0.12, float64(w)*0.15 + bodyCx, bodyCy := float64(w)/2, float64(h)*0.65 + bodyRx, bodyRy := float64(w)*0.22, float64(h)*0.3 + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fx, fy := float64(x), float64(y) + inHead := math.Pow((fx-headCx)/headRx, 2)+math.Pow((fy-headCy)/headRy, 2) < 1 + inBody := math.Pow((fx-bodyCx)/bodyRx, 2)+math.Pow((fy-bodyCy)/bodyRy, 2) < 1 + if inHead || inBody { + img.SetRGBA(x, y, color.RGBA{0, 0, 0, 255}) + } + } + } + // Glitch the silhouette edges + addGlitchBars(img, w, h, 15) + addScanlines(img, w, h, 0.1) +} + +func drawCircuitDream(img *image.RGBA, w, h int) { + accent := []color.RGBA{ + {0, 255, 180, 255}, {0, 150, 255, 255}, {255, 100, 0, 255}, + }[rand.Intn(3)] + + fillBg(img, w, h, color.RGBA{5, 10, 15, 255}, color.RGBA{10, 15, 25, 255}) + + // Grid of circuit-like paths + gridSize := 20 + rand.Intn(20) + for gy := 0; gy < h/gridSize; gy++ { + for gx := 0; gx < w/gridSize; gx++ { + if rand.Float64() > 0.3 { + continue + } + x1 := gx * gridSize + y1 := gy * gridSize + // Draw horizontal or vertical trace + horizontal := rand.Float64() > 0.5 + length := gridSize * (1 + rand.Intn(4)) + thick := 1 + rand.Intn(2) + alpha := 0.3 + rand.Float64()*0.7 + + for d := 0; d < length; d++ { + for t := 0; t < thick; t++ { + var px, py int + if horizontal { + px, py = x1+d, y1+t + } else { + px, py = x1+t, y1+d + } + if px >= 0 && px < w && py >= 0 && py < h { + img.SetRGBA(px, py, color.RGBA{ + clamp(float64(accent.R) * alpha), + clamp(float64(accent.G) * alpha), + clamp(float64(accent.B) * alpha), + 255, + }) + } + } + } + // Node dot at start + for dx := -2; dx <= 2; dx++ { + for dy := -2; dy <= 2; dy++ { + px, py := x1+dx, y1+dy + if px >= 0 && px < w && py >= 0 && py < h { + img.SetRGBA(px, py, accent) + } + } + } + } + } + addGlitchBars(img, w, h, 5) +} + +func drawPlasmaTear(img *image.RGBA, w, h int) { + p1 := rand.Float64() * 10 + p2 := rand.Float64() * 10 + p3 := rand.Float64() * 10 + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fx := float64(x) / float64(w) * 8 + fy := float64(y) / float64(h) * 8 + + v1 := math.Sin(fx*1.5 + p1) + v2 := math.Sin(fy*2.0 + p2) + v3 := math.Sin((fx+fy)*1.2 + p3) + v4 := math.Sin(math.Hypot(fx-4, fy-4) * 1.5) + + v := (v1 + v2 + v3 + v4) / 4.0 + + r := clamp((v*0.5 + 0.5) * 255) + g := clamp((math.Sin(v*math.Pi)*0.5 + 0.5) * 200) + b := clamp(((1-v)*0.5 + 0.5) * 255) + + // Tear: horizontal displacement + if math.Sin(float64(y)*0.05) > 0.92 { + shift := int(math.Sin(float64(y)*0.3) * 40) + nx := x + shift + if nx >= 0 && nx < w { + img.SetRGBA(nx, y, color.RGBA{r, g, b, 255}) + } + } else { + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + } + addScanlines(img, w, h, 0.05) +} + +func drawBitCascade(img *image.RGBA, w, h int) { + shift := rand.Intn(8) + fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{0, 0, 10, 255}) + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + bx, by := x>>2, y>>2 + v1 := (bx ^ by) >> shift + v2 := (bx & by) + v3 := (bx | by) * 3 + + r := uint8((v1 * 13) % 256) + g := uint8((v2 * 7) % 256) + b := uint8((v3 * 5) % 256) + + // Cascade: progressive corruption downward + corruptChance := float64(y) / float64(h) + if rand.Float64() < corruptChance*0.02 { + r, g, b = 255-r, 255-g, 255-b + } + + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + addGlitchBars(img, w, h, int(float64(h)*0.005)) +} + +func drawDeepScan(img *image.RGBA, w, h int) { + scanY := rand.Float64() + accent := []color.RGBA{ + {0, 255, 100, 255}, {255, 50, 50, 255}, {50, 100, 255, 255}, + }[rand.Intn(3)] + + fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{5, 5, 8, 255}) + + // Horizontal bands of data + for y := 0; y < h; y++ { + fy := float64(y) / float64(h) + bandDist := math.Abs(fy - scanY) + intensity := math.Exp(-bandDist * 8) + + for x := 0; x < w; x++ { + noise := float64((x*3571+y*2819)%256) / 256.0 + v := intensity * (0.5 + noise*0.5) + + r := clamp(float64(accent.R) * v) + g := clamp(float64(accent.G) * v) + b := clamp(float64(accent.B) * v) + + // Data blocks + if intensity > 0.3 && (x/6+y/3)%4 == 0 { + r = clamp(float64(r) * 2) + g = clamp(float64(g) * 2) + b = clamp(float64(b) * 2) + } + + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + addScanlines(img, w, h, 0.06) + addGlitchBars(img, w, h, 8) +} + +func drawEntropyWave(img *image.RGBA, w, h int) { + seed1 := rand.Float64() * 100 + seed2 := rand.Float64() * 100 + palette := []color.RGBA{ + {uint8(rand.Intn(256) | 128), uint8(rand.Intn(128)), uint8(rand.Intn(256)), 255}, + {uint8(rand.Intn(128)), uint8(rand.Intn(256) | 128), uint8(rand.Intn(256)), 255}, + {uint8(rand.Intn(256)), uint8(rand.Intn(128)), uint8(rand.Intn(256) | 128), 255}, + } + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fx := float64(x)/float64(w)*6 + seed1 + fy := float64(y)/float64(h)*6 + seed2 + + v := math.Sin(fx*2)*math.Cos(fy*3) + + math.Sin((fx+fy)*1.5)*0.5 + + math.Cos(fx*fy*0.3)*0.3 + + // Normalize -ish to 0..1 + v = v*0.3 + 0.5 + if v < 0 { + v = 0 + } + if v > 1 { + v = 1 + } + + idx := v * float64(len(palette)-1) + i1 := int(idx) + if i1 >= len(palette)-1 { + i1 = len(palette) - 2 + } + frac := idx - float64(i1) + + c := lerpColor(palette[i1], palette[i1+1], frac) + + // Entropy: increasing noise toward bottom + entropy := float64(y) / float64(h) + if rand.Float64() < entropy*0.08 { + c.R ^= uint8(rand.Intn(256)) + c.G ^= uint8(rand.Intn(256)) + c.B ^= uint8(rand.Intn(256)) + } + + img.SetRGBA(x, y, c) + } + } + addGlitchBars(img, w, h, 6) +} + +func rand_Intn(n int) uint8 { + return uint8(rand.Intn(n)) +}