Skip to content

Instantly share code, notes, and snippets.

@radiantly
Last active November 13, 2021 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radiantly/ac373cc3996963fd46755ab34cae61de to your computer and use it in GitHub Desktop.
Save radiantly/ac373cc3996963fd46755ab34cae61de to your computer and use it in GitHub Desktop.
A simple script that allows you to scan and trim multiple pages into a pdf straight from the commandline on Linux using utsushi and imagemagick
#!/usr/bin/python3
import subprocess
from pathlib import Path
from PIL import Image
import rich
import sys
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
def input_char():
try:
tty.setcbreak(sys.stdin)
ch = sys.stdin.read(1)
except:
ch = "q"
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
docname = input("Enter the name of the doc (without .pdf): ").removeprefix(".pdf")
scannedImage = Path("scanned-0.png")
images = []
CLEAR_LINE = "\033[2K\r"
def println(*args):
print(CLEAR_LINE, flush=True, end="")
rich.print(*args, flush=True, end="")
println("Press Enter to start scanning page 1: ")
while input_char() != "\n":
pass
scanning = True
while scanning:
println(f"Scanning page {len(images) + 1} ..")
subprocess.run(
[
"utsushi",
"scan",
"--no-interface",
"--image-format=PNG",
"scanned-%i.png",
]
)
if not scannedImage.exists():
println("Scan failed. Press Enter to try again:")
input_char()
continue
subprocess.run(["convert", "scanned-0.png", "-trim", "-fuzz", "5%", "scanned-0.png"])
println(
f"Scan complete. Do you want to\n"
+ " [bold yellow]\\[s][/bold yellow] start re-scanning the current page\n"
+ " [bold yellow][Enter][/bold yellow] start scanning the next page\n"
+ " [bold yellow][Ctrl+C][/bold yellow] save and exit"
)
while True:
choice = input_char()
if choice in "sq\n":
print("\033[2K\033[1A" * 3, flush=True, end="")
if choice == "s":
break
images.append(Image.open(scannedImage))
println(f"Page {len(images)} added.\n")
if choice == "q":
scanning = False
pdfname = Path(f"{docname}.pdf").absolute()
images[0].save(
pdfname,
"PDF",
resolution=100.0,
save_all=True,
append_images=images[1:],
)
println(f"\nSaved as {pdfname.as_posix()}\n")
break
scannedImage.unlink()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment