Last active
December 8, 2022 10:27
-
-
Save tlatsas/5311181 to your computer and use it in GitHub Desktop.
calculate screen DPI
This file contains 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
#!/usr/bin/env python | |
# calculate screen DPI | |
# supports both python 2 and 3 | |
import re | |
import argparse | |
from math import sqrt | |
from subprocess import check_output | |
__xlib = False | |
try: | |
# note: Xlib is buggy and prints messages in the stdout | |
from Xlib import display | |
__xlib = True | |
except ImportError: | |
#print("Cannot load Xlib, falling back to xrandr") | |
pass | |
def cmd_parse(): | |
"""Parse command line arguments""" | |
parser = argparse.ArgumentParser( | |
description="DPI calculator") | |
parser.add_argument("-r", "--resolution", action="store", | |
help="Screen resolution in WxH format") | |
parser.add_argument("-a", "--ratio", action="store", default="16:9", | |
help="Screen aspect ratio (default: %(default)s)") | |
parser.add_argument("-d", "--dimension", action="store", type=float, | |
required=True, help="Screen diagonal size (in inches)") | |
parser.add_argument("-n", "--normalize", action="store_true", default=False, | |
help=("Normalize DPI to reduce scaling artifacts to GUI that use bitmaps" | |
" (default: %(default)s)")) | |
parser.add_argument("--verbose", action="store_true", default=False, | |
help="Show a more detailed result") | |
return parser.parse_args() | |
def _parse_resolution(resolution): | |
"""Return width and height from a string formatted | |
as 'WidthxHeight'""" | |
return resolution.split('x') | |
def _parse_ratio(ratio): | |
"""Return x and y units from a string formatted as 'X:Y'""" | |
x, y = ratio.split(':') | |
return float(x), float(y) | |
def get_resolution_from_X(): | |
s = display.Display().screen() | |
return (s.width_in_pixels, s.height_in_pixels) | |
def get_resolution_from_xrandr(): | |
output = check_output('xrandr', universal_newlines=True) | |
is_resolution_line = re.compile(r"\*").search | |
for line in iter(output.splitlines()): | |
if is_resolution_line(line): | |
resolution = line.split()[0] | |
break | |
return _parse_resolution(resolution) | |
def get_physical_dimensions(diagonal, w, h): | |
ratio = w/h | |
height = sqrt((diagonal * diagonal) / (1 + ratio * ratio)) | |
width = height * ratio | |
return round(width, 2), round(height, 2) | |
def calculate_dpi(width, height, p_width, p_height): | |
dpi_w = width / p_width | |
dpi_h = height / p_height | |
return dpi_w, dpi_h | |
def normalize_dpi(dpi): | |
dpi_values = (96, 120, 144, 168, 192) | |
new_dpi = dpi | |
minimum = 1000 | |
for dval in dpi_values: | |
difference = abs(dval - dpi) | |
if difference < minimum: | |
minimum = difference | |
new_dpi = dval | |
return new_dpi | |
if __xlib: | |
get_resolution = get_resolution_from_X | |
else: | |
get_resolution = get_resolution_from_xrandr | |
if __name__ == "__main__": | |
args = cmd_parse() | |
if args.resolution: | |
width, height = _parse_resolution(args.resolution) | |
else: | |
width, height = get_resolution() | |
x, y = _parse_ratio(args.ratio) | |
p_width, p_height = get_physical_dimensions(args.dimension, x, y) | |
dpi_w, dpi_h = calculate_dpi(int(width), int(height), p_width, p_height) | |
dpi = int(round(dpi_w)) | |
if args.normalize: | |
dpi = normalize_dpi(dpi) | |
if args.verbose: | |
print("Width: {} Height: {} DPI: {}".format(width, height, dpi)) | |
else: | |
print(dpi) |
Hi @Yaron10,
It has been a long time since I used this (around 2013), so to be honest I am not entirely sure if this is possible. Since then I am guessing that Desktop Environments have gone a long way to property handle dpi 🤔
You can check the Archlinux Wiki at least this is what I used back then. It seems that if you use Gnome you can scale text individually as seen here. But again this depends on the DE you are using.
Hello Tasos,
Thank you for the detailed reply. I do appreciate it. 👍
Best regards.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello Tasos,
I've come across this script googling the following question:
I've recently replaced my old
19" 1360x768
monitor with a23.8" 2560x1440
one.The recommended DPI is 100% in the smaller monitor and 125% in the other.
With 125% DPI, the icons in various applications are re-scaled and I don't like it.
Setting the DPI to 100%, everything is too small.
Is it possible to get a decent display and keep the original images size?
I've also realized that a 19" monitor would be more convenient to me.
So my main question is: how can I be sure that the recommended DPI in a potential monitor should be 100%?
I'd be grateful for your help.
Yaron