Last active
June 9, 2023 14:18
-
-
Save pansila/b239188514407e149f0e92c5e1cad5da to your computer and use it in GitHub Desktop.
Yet another Bing Wallpaper updater, support super resolution. You can run it manually or automatically by Task Scheduler, adding the appropriate triggers, like "At log on", "At startup", "On workstation unlock", etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-*- coding: UTF-8 -*- | |
import sys | |
import time | |
import urllib.request | |
import urllib.error | |
import ctypes | |
import logging | |
import argparse | |
import datetime | |
from io import BytesIO | |
from pathlib import Path | |
from logging.handlers import RotatingFileHandler | |
import requests | |
from PIL import Image | |
BINGAPI = "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&n=9&pid=hp&FORM=BEHPTB&uhd=1&uhdwidth=3840&uhdheight=2160&setmkt={}&setlang=en" | |
BINGWEB = "http://www.bing.com" | |
MODEL_URL = "https://github.com/Saafke/EDSR_Tensorflow/raw/master/models/" | |
CONNECTION_TIMEOUT = 120 | |
SPI_SETDESKWALLPAPER = 20 | |
SPIF_UPDATEINIFILE = 0x1 | |
SPIF_SENDWININICHANGE = 0x2 # forces instant update | |
CHUNK_SIZE = (256, 256) | |
PROXIES = {'http': 'http://127.0.0.1:10809', | |
'https': 'http://127.0.0.1:10809'} | |
LOCALPATH = Path(__file__).parent | |
WALLPAPERFILE = LOCALPATH / "BingWallpaper.jpg" | |
WALLPAPERFILE_SR = LOCALPATH / "BingWallpaper_sr.jpg" | |
LOGFILE = LOCALPATH / "BingWallpaper.log" | |
LASTPICFILE = LOCALPATH / "LastWallpaper.txt" | |
LASTPICFILE.touch() | |
logger = logging.getLogger('BingWallPaper') | |
formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S') | |
stream_handler = logging.StreamHandler(sys.stderr) | |
file_handler = RotatingFileHandler(LOGFILE, maxBytes=100*1024, backupCount=1) | |
file_handler.setFormatter(formatter) | |
logger.addHandler(file_handler) | |
logger.addHandler(stream_handler) | |
logger.setLevel(logging.INFO) | |
def setWallpaper(path): | |
return ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, str(path), SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE) | |
def probe_internet(): | |
""" check the availability of Internet """ | |
for cnt in range(CONNECTION_TIMEOUT): | |
try: | |
urllib.request.urlopen(BINGWEB, timeout=1) | |
except urllib.error.URLError: | |
if cnt % 5 == 0: | |
logger.warning("Internet is not available, retrying...") | |
else: | |
break | |
time.sleep(1) | |
else: | |
raise TimeoutError("Internet is not available") | |
def superres(args, im): | |
import cv2 | |
import numpy as np | |
from cv2 import dnn_superres | |
upsample_factor = args.superres | |
model_file = LOCALPATH / f"EDSR_x{args.superres}.pb" | |
if not model_file.exists() or model_file.stat().st_size == 0: | |
r = requests.get(MODEL_URL + f"EDSR_x{args.superres}.pb", proxies=PROXIES if args.proxy else None) | |
with open(model_file, 'wb') as fout: | |
for chunk in r.iter_content(chunk_size=1024): | |
fout.write(chunk) | |
sr = dnn_superres.DnnSuperResImpl_create() | |
image = cv2.imread(im) | |
sr.readModel(str(model_file)) | |
sr.setModel('edsr', upsample_factor) | |
if args.backend == 'cuda': | |
new_size = (image.shape[1] * upsample_factor, image.shape[0] * upsample_factor) | |
output_img = np.zeros((new_size[1], new_size[0], image.shape[2]), dtype=np.uint8) | |
sr.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) | |
sr.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) | |
for y in range(0, image.shape[0], CHUNK_SIZE[1]): | |
for x in range(0, image.shape[1], CHUNK_SIZE[0]): | |
chunk = image[y:y+CHUNK_SIZE[1], x:x+CHUNK_SIZE[0], :] | |
upsampled_chunk = sr.upsample(chunk) | |
output_img[y*upsample_factor:(y+CHUNK_SIZE[1])*upsample_factor, | |
x*upsample_factor:(x+CHUNK_SIZE[0])*upsample_factor, :] = upsampled_chunk | |
else: | |
output_img = sr.upsample(image) | |
cv2.imwrite(str(WALLPAPERFILE_SR.with_suffix('.png')), output_img) | |
def update_wallpaper(args): | |
r = requests.get(BINGAPI.format(args.region)) | |
urlbase = r.json()['images'][0]['url'] | |
url = BINGWEB + urlbase | |
if not args.force: | |
lastpic = LASTPICFILE.read_text().rstrip() | |
if args.force or urlbase != lastpic: | |
logger.info(urlbase) | |
ret = requests.get(url) | |
im = Image.open(BytesIO(ret.content)) | |
im.save(WALLPAPERFILE, dpi=(600,600)) | |
if args.superres: | |
superres(args, str(WALLPAPERFILE)) | |
if not setWallpaper(WALLPAPERFILE_SR if args.superres else WALLPAPERFILE): | |
logger.error("An error happened when settting wallpaper") | |
return 1 | |
LASTPICFILE.write_text(urlbase) | |
logger.info("Succeeded to set the wallpaper") | |
else: | |
logger.info("Already the latest wall paper") | |
return 0 | |
def run(args): | |
update_time = datetime.time(6, 0) | |
while True: | |
update_wallpaper(args) | |
now = datetime.datetime.now() | |
next_update = datetime.datetime.combine(now.date() + datetime.timedelta(seconds=86400), update_time) - now | |
sleep = next_update.total_seconds() | |
logger.info('Sleep %s seconds to update', sleep) | |
time.sleep(sleep) | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument("-f", "--force", action='store_true', help="force to update the wallpaper") | |
parser.add_argument("-d", "--daemon", action='store_true', help="run in the background") | |
parser.add_argument("-s", "--superres", nargs='?', const=2, type=int, help="use super resolution") | |
parser.add_argument("-b", "--backend", default='cpu', choices=['cpu', 'cuda'], help="specify the backend of opencv") | |
parser.add_argument("-p", "--proxy", action='store_true', help="use network proxy") | |
parser.add_argument("-r", "--region", default='zh-CN', choices=["en-US", "zh-CN", "ja-JP", "en-IN", "pt-BR", "fr-FR", "de-DE", "en-CA", "en-GB", "it-IT", "es-ES", "fr-CA"], help="specify the region of Bing") | |
args = parser.parse_args() | |
if args.daemon: | |
run(args) | |
else: | |
sys.exit(update_wallpaper(args)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dependencies:
and optionally with super resolution (opencv/cpu), be cautious it takes a long time (~5min, Ryzen 5950x)
or build and install opencv/cuda if you want SR GPU accelerated, (~15s, RTX 3060Ti)