Gregory Rudolph
3 years ago
commit
ac61662d6d
7 changed files with 409 additions and 0 deletions
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
kind: pipeline |
||||
type: docker |
||||
name: default |
||||
|
||||
steps: |
||||
- name: Build |
||||
image: golang |
||||
commands: |
||||
- go get ./.. |
||||
- go vet -v |
||||
- env |
||||
- GOOS="linux" go build -ldflags="-w -s" -o BackgroundDaemon-Linux |
||||
- GOOS="windows" go build -ldflags="-w -s" -o BackgroundDaemon-Win.exe |
||||
- GOOS="darwin" go build -ldflags="-w -s" -o BackgroundDaemon-macOS |
||||
- name: gitea_release |
||||
image: plugins/gitea-release |
||||
settings: |
||||
base_url: https://git.nightmare.haus |
||||
api_key: |
||||
from_secret: gitea_token |
||||
files: |
||||
- ./BackgroundDaemon-Linux |
||||
- ./BackgroundDaemon-Win.exe |
||||
- ./BackgroundDaemon-macOS |
||||
checksum: |
||||
- md5 |
||||
- sha1 |
||||
- sha256 |
||||
- sha512 |
||||
- adler32 |
||||
- crc32 |
||||
when: |
||||
event: [tag] |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
*.png |
||||
*.jpg |
||||
*.jpeg |
||||
BackgroundDaemon |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
module git.nightmare.haus/rudi/BackgroundDaemon |
||||
|
||||
go 1.17 |
||||
|
||||
require ( |
||||
github.com/fogleman/gg v1.3.0 |
||||
github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740 |
||||
) |
||||
|
||||
require ( |
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect |
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect |
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect |
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 // indirect |
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect |
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect |
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 // indirect |
||||
gopkg.in/ini.v1 v1.62.0 // indirect |
||||
gopkg.in/yaml.v2 v2.4.0 // indirect |
||||
) |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= |
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= |
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY= |
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= |
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= |
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= |
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= |
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4= |
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= |
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= |
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= |
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= |
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= |
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= |
||||
github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740 h1:X6IDPPN+zrSClp0Q+JiERA//d8L0WcU5MqcGeulCW1A= |
||||
github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740/go.mod h1:WYwPVmM/8szeItLeWkwZSLRvQgrvsvstRzgznR8+E4Q= |
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= |
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= |
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= |
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= |
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= |
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= |
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 h1:5jaG59Zhd+8ZXe8C+lgiAGqkOaZBruqrWclLkgAww34= |
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= |
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= |
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= |
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= |
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= |
@ -0,0 +1,187 @@
@@ -0,0 +1,187 @@
|
||||
package main |
||||
|
||||
// imports
|
||||
import ( |
||||
"encoding/json" |
||||
"flag" |
||||
"fmt" |
||||
"image" |
||||
_ "image/jpeg" |
||||
"image/png" |
||||
"io" |
||||
"log" |
||||
"math/rand" |
||||
"net/http" |
||||
"os" |
||||
"time" |
||||
|
||||
"github.com/kbinani/screenshot" |
||||
"github.com/reujab/wallpaper" |
||||
) |
||||
|
||||
var ( |
||||
sourceImgName string |
||||
outputImgName string |
||||
useNasa bool |
||||
useRandom bool |
||||
setWallpaper bool |
||||
useSketch bool |
||||
nasaAPI string |
||||
totalCycleCount = 5000 |
||||
) |
||||
|
||||
func init() { |
||||
flag.BoolVar(&useNasa, "nasa", false, "Use NASA Astronomy Pic Of the Day as a source image") |
||||
flag.BoolVar(&setWallpaper, "set", false, "Set user wallpaper to the output.") |
||||
flag.BoolVar(&useRandom, "unsplash", false, "Use random unsplash image for seed (Will grab dimensions from background or source if set)") |
||||
flag.BoolVar(&useSketch, "sketch", false, "Use Sketch to generate a new image.") |
||||
flag.StringVar(&sourceImgName, "source", "", "Source image, will override current background") |
||||
flag.StringVar(&outputImgName, "output", "out.png", "Output image filename") |
||||
flag.StringVar(&nasaAPI, "nasa-key", "DEMO_KEY", "Supply your own API Key for NASA APOD") |
||||
} |
||||
|
||||
func main() { |
||||
flag.Parse() |
||||
background, err := wallpaper.Get() |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
bounds := screenshot.GetDisplayBounds(0) |
||||
|
||||
var img image.Image |
||||
if useRandom { |
||||
img, err = loadRandomUnsplashImage(bounds.Dx(), bounds.Dy()) |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
} else if useNasa { |
||||
resp, err := http.Get(fmt.Sprintf("https://api.nasa.gov/planetary/apod?api_key=%+v", nasaAPI)) |
||||
if err != nil { |
||||
log.Fatalf("\nUnable to get NASA API Response\n") |
||||
return |
||||
} |
||||
var apod APODResponse |
||||
decoder := json.NewDecoder(resp.Body) |
||||
err = decoder.Decode(&apod) |
||||
if err != nil { |
||||
log.Fatalf("\nUnable to decode APOD Response: \n%+v\n", resp) |
||||
return |
||||
} |
||||
file, err := os.CreateTemp(".", apod.Hdurl) |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
defer os.Remove(file.Name()) |
||||
downloadFile(file.Name(), apod.Hdurl) |
||||
img, err = loadImage(file.Name()) |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
} else if len(sourceImgName) > 0 { |
||||
img, err = loadImage(sourceImgName) |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
} else { |
||||
img, err = loadImage(background) |
||||
if err != nil { |
||||
log.Println(background) |
||||
log.Panicln(err) |
||||
} |
||||
} |
||||
|
||||
s := NewSketch(img, UserParams{ |
||||
StrokeRatio: 0.75, |
||||
DestWidth: bounds.Dx(), |
||||
DestHeight: bounds.Dy(), |
||||
InitialAlpha: 0.1, |
||||
StrokeReduction: 0.002, |
||||
AlphaIncrease: 0.06, |
||||
StrokeInversionThreshold: 0.05, |
||||
StrokeJitter: int(0.1 * float64(bounds.Dx())), |
||||
MinEdgeCount: 3, |
||||
MaxEdgeCount: 8, |
||||
}) |
||||
|
||||
rand.Seed(time.Now().Unix()) |
||||
|
||||
if useSketch { |
||||
for i := 0; i < totalCycleCount; i++ { |
||||
s.Update() |
||||
} |
||||
|
||||
saveOutput(s.Output(), outputImgName) |
||||
} else { |
||||
|
||||
saveOutput(img, outputImgName) |
||||
} |
||||
|
||||
if setWallpaper { |
||||
err = wallpaper.SetFromFile(outputImgName) |
||||
if err != nil { |
||||
log.Panicln(err) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func loadRandomUnsplashImage(width, height int) (image.Image, error) { |
||||
url := fmt.Sprintf("https://source.unsplash.com/random/%dx%d", width, height) |
||||
res, err := http.Get(url) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
defer res.Body.Close() |
||||
|
||||
img, _, err := image.Decode(res.Body) |
||||
return img, err |
||||
} |
||||
|
||||
func loadImage(src string) (image.Image, error) { |
||||
file, _ := os.Open(sourceImgName) |
||||
defer file.Close() |
||||
img, _, err := image.Decode(file) |
||||
return img, err |
||||
} |
||||
|
||||
func saveOutput(img image.Image, filePath string) error { |
||||
f, err := os.Create(filePath) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer f.Close() |
||||
|
||||
// Encode to `PNG` with `DefaultCompression` level
|
||||
// then save to file
|
||||
err = png.Encode(f, img) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
// https://stackoverflow.com/questions/33845770/how-do-i-download-a-file-with-a-http-request-in-go-language/33845771
|
||||
func downloadFile(filepath string, url string) (err error) { |
||||
|
||||
// Create the file
|
||||
out, err := os.Create(filepath) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer out.Close() |
||||
|
||||
// Get the data
|
||||
resp, err := http.Get(url) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer resp.Body.Close() |
||||
|
||||
// Writer the body to file
|
||||
_, err = io.Copy(out, resp.Body) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
} |
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
package main |
||||
|
||||
// imports
|
||||
import ( |
||||
"github.com/fogleman/gg" |
||||
"image" |
||||
"image/color" |
||||
"math/rand" |
||||
) |
||||
|
||||
// imports
|
||||
|
||||
type UserParams struct { |
||||
StrokeRatio float64 |
||||
DestWidth int |
||||
DestHeight int |
||||
InitialAlpha float64 |
||||
StrokeReduction float64 |
||||
AlphaIncrease float64 |
||||
StrokeInversionThreshold float64 |
||||
StrokeJitter int |
||||
MinEdgeCount int |
||||
MaxEdgeCount int |
||||
} |
||||
|
||||
type Sketch struct { |
||||
UserParams // embed for easier access
|
||||
source image.Image |
||||
dc *gg.Context |
||||
sourceWidth int |
||||
sourceHeight int |
||||
strokeSize float64 |
||||
initialStrokeSize float64 |
||||
} |
||||
|
||||
func NewSketch(source image.Image, userParams UserParams) *Sketch { |
||||
s := &Sketch{UserParams: userParams} |
||||
bounds := source.Bounds() |
||||
s.sourceWidth, s.sourceHeight = bounds.Max.X, bounds.Max.Y |
||||
s.initialStrokeSize = s.StrokeRatio * float64(s.DestWidth) |
||||
s.strokeSize = s.initialStrokeSize |
||||
|
||||
canvas := gg.NewContext(s.DestWidth, s.DestHeight) |
||||
canvas.SetColor(color.Black) |
||||
canvas.DrawRectangle(0, 0, float64(s.DestWidth), float64(s.DestHeight)) |
||||
canvas.FillPreserve() |
||||
|
||||
s.source = source |
||||
s.dc = canvas |
||||
return s |
||||
} |
||||
|
||||
func (s *Sketch) Update() { |
||||
rndX := rand.Float64() * float64(s.sourceWidth) |
||||
rndY := rand.Float64() * float64(s.sourceHeight) |
||||
r, g, b := rgb255(s.source.At(int(rndX), int(rndY))) |
||||
|
||||
destX := rndX * float64(s.DestWidth) / float64(s.sourceWidth) |
||||
destX += float64(randRange(s.StrokeJitter)) |
||||
destY := rndY * float64(s.DestHeight) / float64(s.sourceHeight) |
||||
destY += float64(randRange(s.StrokeJitter)) |
||||
edges := s.MinEdgeCount + rand.Intn(s.MaxEdgeCount-s.MinEdgeCount+1) |
||||
|
||||
s.dc.SetRGBA255(r, g, b, int(s.InitialAlpha)) |
||||
s.dc.DrawRegularPolygon(edges, destX, destY, s.strokeSize, rand.Float64()) |
||||
s.dc.FillPreserve() |
||||
|
||||
if s.strokeSize <= s.StrokeInversionThreshold*s.initialStrokeSize { |
||||
if (r+g+b)/3 < 128 { |
||||
s.dc.SetRGBA255(255, 255, 255, int(s.InitialAlpha*2)) |
||||
} else { |
||||
s.dc.SetRGBA255(0, 0, 0, int(s.InitialAlpha*2)) |
||||
} |
||||
} |
||||
s.dc.Stroke() |
||||
|
||||
s.strokeSize -= s.StrokeReduction * s.strokeSize |
||||
s.InitialAlpha += s.AlphaIncrease |
||||
} |
||||
|
||||
func (s *Sketch) Output() image.Image { |
||||
return s.dc.Image() |
||||
} |
||||
|
||||
func rgb255(c color.Color) (r, g, b int) { |
||||
r0, g0, b0, _ := c.RGBA() |
||||
return int(r0 / 257), int(g0 / 257), int(b0 / 257) |
||||
} |
||||
|
||||
func randRange(max int) int { |
||||
return -max + rand.Intn(2*max) |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package main |
||||
|
||||
type APODResponse struct { |
||||
Date string `json:"date"` |
||||
Explanation string `json:"explanation"` |
||||
Hdurl string `json:"hdurl"` |
||||
MediaType string `json:"media_type"` |
||||
ServiceVersion string `json:"service_version"` |
||||
Title string `json:"title"` |
||||
URL string `json:"url"` |
||||
} |
||||
|
||||
type MarsResponse struct { |
||||
Photos []struct { |
||||
ID int `json:"id"` |
||||
Sol int `json:"sol"` |
||||
Camera struct { |
||||
ID int `json:"id"` |
||||
Name string `json:"name"` |
||||
RoverID int `json:"rover_id"` |
||||
FullName string `json:"full_name"` |
||||
} `json:"camera"` |
||||
ImgSrc string `json:"img_src"` |
||||
EarthDate string `json:"earth_date"` |
||||
Rover struct { |
||||
ID int `json:"id"` |
||||
Name string `json:"name"` |
||||
LandingDate string `json:"landing_date"` |
||||
LaunchDate string `json:"launch_date"` |
||||
Status string `json:"status"` |
||||
} `json:"rover"` |
||||
} `json:"photos"` |
||||
} |
Loading…
Reference in new issue