132 lines
3.3 KiB
Python
132 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
r"""
|
|
#!/bin/sh
|
|
|
|
name="$(date +"scrot_%Y.%m.%d_%H.%M.%S.png")";
|
|
out_path="$HOME/images/shots/$name";
|
|
|
|
info="$(xwininfo)";
|
|
|
|
width="$(echo "$info" | grep -oP 'Width: \d+' | grep -oP '\d+')";
|
|
height="$(echo "$info" | grep -oP 'Height: \d+' | grep -oP '\d+')";
|
|
abs_x="$(echo "$info" | grep -oP 'Absolute upper-left X:\s+\d+' | grep -oP '\d+')";
|
|
abs_y="$(echo "$info" | grep -oP 'Absolute upper-left Y:\s+\d+' | grep -oP '\d+')";
|
|
|
|
abs_x=$((abs_x - 40));
|
|
abs_y=$((abs_y - 40));
|
|
width=$((width + 80));
|
|
height=$((height + 80));
|
|
|
|
# scrot -b -a "${abs_x},${abs_y},${width},${height}" "$name" || exit;
|
|
maim --geometry "${width}x${height}+${abs_x}+${abs_y}" --capturebackground "$name" || exit;
|
|
|
|
mv "$name" "$out_path";
|
|
|
|
xclip -selection clipboard -t 'image/png' < "$out_path";
|
|
|
|
notify-send -a "scrot" "Saved screenshot" "${out_path}";
|
|
"""
|
|
|
|
from PIL import Image, ImageFile, PngImagePlugin, ImageFilter
|
|
from subprocess import PIPE, Popen, check_call, check_output, CalledProcessError
|
|
from typing import NamedTuple
|
|
from datetime import datetime
|
|
from json import dumps
|
|
from pathlib import Path
|
|
|
|
|
|
PADDING = 32
|
|
taken_time = datetime.now()
|
|
output_path = Path(f"~/images/shots/scrot_{taken_time:%Y.%m.%d_%H.%M.%S}.png").expanduser()
|
|
|
|
|
|
class Geometry(NamedTuple):
|
|
x: int
|
|
y: int
|
|
w: int
|
|
h: int
|
|
|
|
def __str__(self):
|
|
return f"{self.w}x{self.h}{self.x:+d}{self.y:+d}"
|
|
|
|
|
|
with ImageFile.Parser() as parser:
|
|
with Popen([
|
|
"scrot", "--file", "-", "--silent", "--format", "bmp"
|
|
], stdout=PIPE) as proc:
|
|
if not proc.stdout:
|
|
raise ValueError(
|
|
"WHY the FUCK I have to check for it EVERY time???"
|
|
)
|
|
while chunk := proc.stdout.read(131072):
|
|
parser.feed(chunk)
|
|
|
|
screenshot = parser.close()
|
|
|
|
try:
|
|
output = check_output([
|
|
"slop",
|
|
"-l",
|
|
"-c", "0.3,0.4,0.6,0.4",
|
|
"-f", "%x %y %w %h",
|
|
"--tolerance", "999999",
|
|
], encoding="utf-8",)
|
|
except CalledProcessError:
|
|
exit(1)
|
|
|
|
original_geometry = Geometry(*map(int, output.split()))
|
|
padded_geometry = Geometry(
|
|
original_geometry.x - PADDING,
|
|
original_geometry.y - PADDING,
|
|
original_geometry.w + PADDING * 2,
|
|
original_geometry.h + PADDING * 2,
|
|
)
|
|
|
|
with Image.new("RGBA", (padded_geometry.w, padded_geometry.h), 0) as canvas:
|
|
|
|
backdrop = screenshot.crop((
|
|
padded_geometry.x,
|
|
padded_geometry.y,
|
|
padded_geometry.x + padded_geometry.w,
|
|
padded_geometry.y + padded_geometry.h,
|
|
))
|
|
|
|
canvas.paste(
|
|
backdrop
|
|
.filter(ImageFilter.GaussianBlur(2))
|
|
.filter(ImageFilter.MedianFilter(5)),
|
|
(0, 0),
|
|
)
|
|
|
|
crop = screenshot.crop((
|
|
original_geometry.x,
|
|
original_geometry.y,
|
|
original_geometry.x + original_geometry.w,
|
|
original_geometry.y + original_geometry.h,
|
|
))
|
|
|
|
canvas.paste(crop, (PADDING, PADDING))
|
|
|
|
data = PngImagePlugin.PngInfo()
|
|
|
|
data.add_text( "fscr", dumps({
|
|
"timestamp": taken_time.timestamp(),
|
|
"geometry": {
|
|
"x": original_geometry.x,
|
|
"y": original_geometry.y,
|
|
"w": original_geometry.w,
|
|
"h": original_geometry.h,
|
|
},
|
|
}))
|
|
|
|
canvas.save(output_path, pnginfo=data)
|
|
|
|
|
|
check_call([
|
|
"xclip",
|
|
"-sel", "c",
|
|
"-i", output_path,
|
|
"-t", "image/png"
|
|
])
|