You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.1 KiB

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()
bounds := screenshot.GetDisplayBounds(0)
var img image.Image
var err error
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 {
background, err := wallpaper.Get()
if err != nil {
log.Panicln(err)
}
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
}