Как стать автором
Обновить

Комментарии 17

Спасибо. Но главное, как мне кажется, понимать откуда это всё берется и как работает. Цель статьи пролить немножечко света на этот аспект.
Ну просто значительно удобнее, чем с линейкой. Как я понимаю, у вас 15.6", вводим 1600×900×15.6" — получаем те же 117 DPI.

А после этого всё остальное не поехало по размеру/пикселам и т.д.?

А почему оно должно было поехать?

По размеру/пикселам и т.д.)
Ламповая статья, помню такие на ЛОРе ещё. Последнее время правда о таком не задумываешься.
Эх, 2007 год, проприетарные драйвера для nvidia, сборка генты, тюнинг ядра ...)

> По размеру/пикселам и т.д.)

Ну разумеется немножко изменилось всё и в браузере, шрифты стали как-то чуточку больше что ли. Но это через полчаса работы уже не замечаешь. Отображение везде корректное, ничто не наползает друг на друга и т.д.

> Последнее время правда о таком не задумываешься.

А я вот не понял, что позволяет об этом не задумываться? Ладно в Винде есть к каждому монику идет inf, в котором это прописано. Если юзать EDID, то описанная погрешность не устранима, поэтому винда скорее всего использует EDID только для того, чтобы айдишник моника считать и соответствующий inf подтянуть. Плюс в винде есть встроенный механизм по калибровке DPI. В линуксе этого всего нет, ИМХО, до сих пор. Мне кажется, что просто большинство не догадывается, что их экранные сантиметры под Linux'ом на самом деле не сантиметры вовсе.

Почему не задумываюсь? Да просто лично мне наверное без разницы является ли 1 см в IDE действительно одним сантиметром, или на самом деле 1.5.
Я просто к тому что мне сама статья понравилась, посыл ламповый) А вы сразу в штыки как-то(

Не-не! Я вообще никак в штыки не воспринимал. Просто думал, может быть, вы прольете свет на то, что позволяет не задумываться. Я в это дело влезаю раз в пять лет, когда новый монитор/лэптоп появляется. И каждый раз одно и тоже. В это раз вот даже с GTK3 новый нюанс всплыл.

А было время, вручную писал modeline'ы для ЭЛТ-шных моников, чтобы выжимать из них все соки по частоте обновления. Ибо у меня перефирийной зрение очень чувствительно и до 90 Hz ловит развертку.

Я за 10 лет, крайне редко работаю с печатью, а то что печатаю не требует таких нюансов. В остальном, браузер, ide, терминал и мессенджеры нормально выглядят даже с этим искажением.

Проблема №1 — протокол EDID передает линейные размеры экрана с точностью до см.
Вообще-то оно до мм выдаёт, но на некоторых мониторах и особенно телевизорах безбожно врёт
#!/usr/bin/lua

function edid_geometry(edid)
	if #edid<69 then error "invalid edid" end
	local a,b=string.unpack("I3I3",edid:sub(0x39))
	local r={ cx=(a&255)+((a>>20)&15)*256, cy=(b&255)+((b>>20)&15)*256 }
	r.w_cm,r.h_cm=string.unpack("BB",edid:sub(0x16,0x17))
	a=string.unpack("I3",edid:sub(0x43,0x45))
	r.w_mm=(a&255)+((a>>20)&15)*256
	r.h_mm=((a>>8)&255)+((a>>16)&15)*256
	r.xdpi=r.cx/r.w_mm*25.4
	r.ydpi=r.cy/r.h_mm*25.4
	return r
end

function hex(s,r) r=r or ""
	s:gsub("%x%x",function(x)
		x=tonumber(x,16) r=r..string.char(x)
	end)
	return r
end

function query_edid_windows(monitor)
	monitor=monitor or 0
	local function query_reg(path,val,pat,res)
		local p,err=io.popen('reg query "HKLM\\System\\CurrentControlSet\\'
			..path..'" /v '..val)
		if not p then error(err) end
		for line in p:lines() do
			local t=line:match(pat)
			if t then res=t break end
		end
		p:close();
		return res
	end
	local mon=query_reg("services\\monitor\\Enum",
		monitor,"REG_SZ%s+(.+)")
	if not mon then error("no monitor "..monitor) end
	local edid=query_reg("Enum\\"..mon.."\\Device Parameters",
		"EDID","REG_BINARY%s+(.+)")
	if not edid then error("no edid for "..monitor..'-'..mon) end
	return hex(edid)
end

function query_edid_linux(prm)
	prm=prm or {}
	prm.fb=prm.fb or 0
	prm.card=prm.card or 0
	prm.name=prm.name or 'LVDS-1' -- LVDS-1, VGA-1
	local path=string.format(
		"/sys/class/graphics/fb%d/device/drm/card%d/card%d-%s/edid",
		prm.fb,prm.card,prm.card,prm.name)
	local f,err=io.popen([[cat ]]..path..[[ | hexdump -e '16/1 "%02x " "\n"']])
	if not f then error(err) end
	local edid=f:read"a"
	f:close()
	return hex(edid)
end

function is_linux() 
	return package.config:sub(1,1)=='/'
end

function get_edid() 
	if is_linux() then
		return query_edid_linux{ name='LVDS-1' }
	else
		return query_edid_windows(0)
	end
end

edid=get_edid()
g=edid_geometry(edid)
print(string.format("monitor %d*%dpx %d*%dmm xdpi=%.2f ydpi=%.2f",
	g.cx,g.cy,g.w_mm,g.h_mm,g.xdpi,g.ydpi))

L=100
print(string.format("L=%.fmm = %.1fpx",L,L*g.cx/g.w_mm))

Output:
monitor 1920*1080px 344*194mm xdpi=141.77 ydpi=141.40
L=100mm = 558.1px

Хм… вы правы. Но почему-то не применяется эта инфа иксами. Возможно проблема в том, что они напарываются на unknown vendor specific block

[304898.400] (II) modeset(0): EDID for output LVDS-1
[304898.400] (II) modeset(0): Manufacturer: LEN Model: 40b1 Serial#: 0
[304898.400] (II) modeset(0): Year: 2010 Week: 0
[304898.400] (II) modeset(0): EDID Version: 1.3
[304898.400] (II) modeset(0): Digital Display Input
[304898.400] (II) modeset(0): Max Image Size [cm]: horiz.: 34 vert.: 19
[304898.400] (II) modeset(0): Gamma: 2.20
[304898.400] (II) modeset(0): DPMS capabilities: StandBy Suspend Off
[304898.400] (II) modeset(0): Supported color encodings: RGB 4:4:4 YCrCb 4:4:4
[304898.400] (II) modeset(0): First detailed timing is preferred mode
[304898.400] (II) modeset(0): redX: 0.620 redY: 0.340 greenX: 0.330 greenY: 0.570
[304898.400] (II) modeset(0): blueX: 0.150 blueY: 0.060 whiteX: 0.313 whiteY: 0.329
[304898.400] (II) modeset(0): Manufacturer's mask: 0
[304898.400] (II) modeset(0): Supported detailed timing:
[304898.400] (II) modeset(0): clock: 96.3 MHz Image Size: 344 x 194 mm
[304898.400] (II) modeset(0): h_active: 1600 h_sync: 1648 h_sync_end 1680 h_blank_end 1726 h_border: 0
[304898.400] (II) modeset(0): v_active: 900 v_sync: 902 v_sync_end 907 v_blanking: 930 v_border: 0
[304898.400] (II) modeset(0): Supported detailed timing:
[304898.400] (II) modeset(0): clock: 80.6 MHz Image Size: 344 x 194 mm
[304898.400] (II) modeset(0): h_active: 1600 h_sync: 1648 h_sync_end 1680 h_blank_end 1734 h_border: 0
[304898.401] (II) modeset(0): v_active: 900 v_sync: 902 v_sync_end 907 v_blanking: 930 v_border: 0
[304898.401] (II) modeset(0): Unknown vendor-specific block f
[304898.401] (II) modeset(0): LTN156KT02401
[304898.401] (II) modeset(0): EDID (in hex):
[304898.401] (II) modeset(0): 00ffffffffffff0030aeb14000000000
[304898.401] (II) modeset(0): 0014010380221378eac8959e57549226
[304898.401] (II) modeset(0): 0f505400000001010101010101010101
[304898.401] (II) modeset(0): 0101010101019f25407e60841e303020
[304898.401] (II) modeset(0): 250058c2100000197f1f408660841e30
[304898.401] (II) modeset(0): 3020250058c2100000190000000f00a9
[304898.401] (II) modeset(0): 0932a909281609004ca34b54000000fe
[304898.401] (II) modeset(0): 004c544e3135364b5430323430310095

Работаю с Qt, проблем с получением dpi не наблюдаю, в том числе и с hidpi дисплеями.
Часто выравниваю масштабирование при отрисовке на физический пиксель, что бы не было размытия.

Я тоже больше приверженец Qt, чем GTK. Но как пользователи, мы иногда не можем выбирать.
Вообще-то это правильно называется PPI
DPI — это в основном про субпиксели, из которых состоят цветные пиксели при печати например, на струйном принтере.
Как бы это не называлось. Но достоверной информации как нарисовать ровно 10см отрезок на мониторе нет. EDID бывает заметно не точен, а иногда вообще не связан с физическими размерами от слова совсем.

Калибровка спасет отца русской демократии)

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории