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

115 lines
3.9 KiB
Text
Raw Normal View History

2012-07-06 14:19:54 +02:00
#!/usr/bin/env python
# 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.
import os
import random
import string
import optparse
import tempfile
2012-07-06 14:19:54 +02:00
import xcb
import xcb.xproto
import xcb.xinerama
import Image
parser = optparse.OptionParser()
parser.add_option("-d", "--directory", dest="directory", default=".",
help="search for images in DIRECTORY", metavar="DIRECTORY")
2012-07-06 14:19:54 +02:00
parser.add_option("-t", "--target", dest="target", default="background.jpg",
help="write background to FILE", metavar="FILE")
2012-07-06 14:19:54 +02:00
parser.add_option("-c", "--crop", dest="crop", action="store_true",
help="crop image instead of centering them")
options, args = parser.parse_args()
assert not args, "No additional arguments are accepted"
background = None
# Get display size
display = xcb.connect()
root = display.get_setup().roots[0]
background = Image.new('RGB', (root.width_in_pixels, root.height_in_pixels))
# Query xinerama (not randr since the query is longer)
try:
xinerama = display(xcb.xinerama.key)
except xcb.ExtensionException:
xinerama = None
if not xinerama or not xinerama.IsActive().reply().state:
screens = [(background.size[0], background.size[1], 0, 0)]
else:
screens = [(screen.width, screen.height, screen.x_org, screen.y_org)
for screen in xinerama.QueryScreens().reply().screen_info]
screens.sort(key=lambda screen: -screen[0]*screen[1])
# 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:
if string.lower(os.path.splitext(i)[1]) 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]
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:
target = root.width_in_pixels * 100 / root.height_in_pixels
ratios = [image.size[0] * 100 / image.size[1] for image in images]
try:
index = ratios.index(target)
images = [images[index]]
except ValueError:
pass
print("wallpaper: {}".format(" + ".join(
["`%s`" % x.filename[(len(options.directory) + 1):]
for x in images])))
# Link chosen wallpapers
for idx, image in enumerate(images):
target = "{}.{}".format(options.target, idx)
if os.path.lexists(target):
os.remove(target)
os.symlink(os.path.abspath(image.filename), target)
2012-07-06 14:19:54 +02:00
2018-08-01 14:24:53 +02:00
if len(screens) > 1 and len(images) == 1:
# Wide wallpaper
if image.size != (root.width_in_pixels, root.height_in_pixels):
image = image.resize((root.width_in_pixels, root.height_in_pixels),
Image.CUBIC)
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
imx, imy = x, image.size[1]*x/image.size[0]
if (options.crop and imy < y) or (not options.crop and imy > y):
imx, imy = image.size[0]*y/image.size[1], y
if image.size != (imx, imy):
image = image.resize((imx, imy), Image.CUBIC)
if options.crop:
image = image.crop(((imx-x)/2, (imy-y)/2,
imx-(imx-x)/2, imy-(imy-y)/2))
background.paste(image, (offsetx, offsety))
else:
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(
delete=False,
dir=os.path.dirname(os.path.realpath(options.target))) as tmp:
background.save(tmp, "png")
os.rename(tmp.name, options.target)