vincentbernat.i3wm-configur.../bin/build-wallpaper

136 lines
4.1 KiB
Text
Raw Normal View History

2018-08-05 22:37:14 +02:00
#!/usr/bin/env python3
2012-07-06 14:19:54 +02:00
# Build a multi screen wallpaper
# First argument is the directory where the wallpapers can be
# found. We use xinerama to know the dimension of each screen.
2018-08-05 22:37:14 +02:00
from __future__ import print_function, unicode_literals, division
2012-07-06 14:19:54 +02:00
import os
import random
import optparse
import tempfile
2012-07-06 14:19:54 +02:00
2020-02-06 21:59:29 +01:00
from Xlib import display
2018-08-05 22:37:14 +02:00
from Xlib.ext import randr
2012-07-06 14:19:54 +02:00
2018-08-05 22:37:14 +02:00
from PIL import Image
2012-07-06 14:19:54 +02:00
parser = optparse.OptionParser()
2021-07-17 09:13:26 +02:00
parser.add_option(
"-d",
"--directory",
dest="directory",
default=".",
help="search for images in DIRECTORY",
metavar="DIRECTORY",
)
parser.add_option(
"-t",
"--target",
dest="target",
default="background.png",
help="write background to FILE",
metavar="FILE",
)
parser.add_option(
"-c",
"--crop",
dest="crop",
action="store_true",
help="crop image instead of centering them",
)
parser.add_option(
"--compression", default=0, type=int, help="compression level when saving"
)
2012-07-06 14:19:54 +02:00
options, args = parser.parse_args()
assert not args, "No additional arguments are accepted"
background = None
# Get display size
2018-08-05 22:37:14 +02:00
d = display.Display()
screen = d.screen()
window = screen.root.create_window(0, 0, 1, 1, 1, screen.root_depth)
2021-07-17 09:13:26 +02:00
background = Image.new("RGB", (screen.width_in_pixels, screen.height_in_pixels))
2018-08-05 22:37:14 +02:00
# Query randr extension
screens = []
screen_resources = randr.get_screen_resources_current(window)
2018-08-05 22:37:14 +02:00
for output in screen_resources.outputs:
2021-07-17 09:13:26 +02:00
output_info = randr.get_output_info(window, output, screen_resources.timestamp)
2018-08-05 22:37:14 +02:00
if output_info.crtc == 0:
continue
2021-07-17 09:13:26 +02:00
crtc_info = randr.get_crtc_info(window, output_info.crtc, output_info.timestamp)
screens.append((crtc_info.width, crtc_info.height, crtc_info.x, crtc_info.y))
2018-08-05 22:37:14 +02:00
if not screens:
2012-07-06 14:19:54 +02:00
screens = [(background.size[0], background.size[1], 0, 0)]
2021-07-17 09:13:26 +02:00
screens.sort(key=lambda screen: -screen[0] * screen[1])
2012-07-06 14:19:54 +02:00
# Get as many random image as we have screens
images = []
2018-08-01 14:24:53 +02:00
for base, _, files in os.walk(os.path.join(options.directory)):
2012-07-06 14:19:54 +02:00
for i in files:
2021-07-17 09:13:26 +02:00
if os.path.splitext(i)[1].lower() in (".jpg", ".jpeg", ".png"):
2018-08-01 14:24:53 +02:00
images.append(os.path.join(base, i))
images = random.sample(images, len(screens))
images = [Image.open(image) for image in images]
2021-07-17 09:13:26 +02:00
images.sort(key=lambda im: -im.size[0] * im.size[1])
images = images[: len(screens)]
2018-08-01 14:24:53 +02:00
# If more than one screen and one image has the right aspect ratio,
# use it.
if len(screens) > 1:
2018-08-05 22:37:14 +02:00
target = screen.width_in_pixels * 100 / screen.height_in_pixels
2018-08-01 14:24:53 +02:00
ratios = [image.size[0] * 100 / image.size[1] for image in images]
try:
index = ratios.index(target)
images = [images[index]]
except ValueError:
pass
2021-07-17 09:13:26 +02:00
print(
"wallpaper: {}".format(
" + ".join(
["`%s`" % x.filename[(len(options.directory) + 1) :] for x in images]
)
)
)
2018-08-01 14:24:53 +02:00
if len(screens) > 1 and len(images) == 1:
# Wide wallpaper
image = images[0]
2018-08-05 22:37:14 +02:00
if image.size != (screen.width_in_pixels, screen.height_in_pixels):
2021-07-17 09:13:26 +02:00
image = image.resize(
(screen.width_in_pixels, screen.height_in_pixels), Image.CUBIC
)
2018-08-01 14:24:53 +02:00
background.paste(image, (0, 0))
else:
for index in range(len(screens)):
x, y, offsetx, offsety = screens[index]
image = images[index]
# Find the right size for the screen
2021-07-17 09:13:26 +02:00
imx, imy = x, image.size[1] * x // image.size[0]
2018-08-01 14:24:53 +02:00
if (options.crop and imy < y) or (not options.crop and imy > y):
2021-07-17 09:13:26 +02:00
imx, imy = image.size[0] * y // image.size[1], y
2018-08-01 14:24:53 +02:00
if image.size != (imx, imy):
image = image.resize((imx, imy), Image.CUBIC)
if options.crop:
2021-07-17 09:13:26 +02:00
image = image.crop(
((imx - x) / 2, (imy - y) / 2, imx - (imx - x) / 2, imy - (imy - y) / 2)
)
2018-08-01 14:24:53 +02:00
background.paste(image, (offsetx, offsety))
else:
2021-07-17 09:13:26 +02:00
background.paste(image, ((x - imx) / 2 + offsetx, (y - imy) / 2 + offsety))
2012-07-06 14:19:54 +02:00
# Save
assert background, "Don't know the size of the display area"
with tempfile.NamedTemporaryFile(
2021-07-17 09:13:26 +02:00
delete=False, dir=os.path.dirname(os.path.realpath(options.target))
) as tmp:
background.save(tmp, "png", compress_level=options.compression)
os.rename(tmp.name, options.target)