Crisp up-scaled images for displays with 150% DPI scale factor (Firefox 74+)

Prevents blurry anti-aliased borders between picture sampling areas ("pixels").

Устаревшая версия за 17.06.2020. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Advertisement:

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

Advertisement:

/* ==UserStyle==
@name        Crisp up-scaled images for displays with 150% DPI scale factor (Firefox 74+)
@description Prevents blurry anti-aliased borders between picture sampling areas ("pixels").
@namespace   myfonj
@version     1.0.1
@license     CC0 - Public Domain
==/UserStyle== */

@-moz-document regexp(".*\\.(png|gif)(\\?.*)?(#.*)?$") {
/*
"DPI Zoom (scale) factor" can be obtained with JavaScript:

window.devicePixelRatio

for 150% DPI scale factor at page with 100% zoom level this should be 1.5

min zoom is 30 %
max zoom is 300 %

[ctrl] + [mouse wheel] modifies DPI consistently by +- 10 %.

[ctrl] + [+ / -] modifies DPI in prefefined values - powers of 10 % with two exceptions: 30, 50, *67*, 80, 90, 100, 110, 120, *133*, 150, 170, 200, 240, 300. Those exceptions and derived values [1] are not in scope of this stylesheet. 

[1] in theory combining wheel and keyboard zoom one could possibly get 30, *33*, *37*, 40, *43*, *47*, 50 (...) zoom factors.

a.k.a. resolution value for media query
this file expects "normal" scale factor to be *150%*
what normally causes ugly blurry "scaled down" images
this style undoes that scale so that image pixels are mapped to physical pixels and anti-aliasing is suppressed
producing crisp scaled image in "100% zoom" (then it is mapped to 2×2 pixels) and controls resizing with `transform` to maintain crispness and predictable dimension in most zoom levels.
*/


/*
100% page zoom
1 = __ monitor scale × __ transform scale to "undo"
1 = 1.25 × 0.8
1 = 1.5 × 0.6666666666666
1 = 2 × 0.5
strangemesses:
?? __ page zoom at monitor set to __ scale is matched by `(resolution: __)`
!! 90% 100% 0.895522445440292259dppx
OK 50% 100% 0.5dppx
OK 100% 125% 1.25dppx
!! 100% 175% 1.76470595598220835dppx

centering crisp image of odd dimesion would produce unwanted "notch" from rounding
drawbacks: 
- zooming is funky: apparently "zoom" is done by ajdusting DPI factor, so sometimes some of our rules hits

[width][height] = image fits viewport
*/


@media
(resolution: 0.75dppx),
(resolution: 0.8955223880597015dppx),
(resolution: 1.0526315789473684dppx),
(resolution: 1.2dppx),
(resolution: 1.3636363636363635dppx),
(resolution: 1.50dppx),
(resolution: 1.6666666666666667dppx),
(resolution: 1.8181818181818181dppx),
(resolution: 1.935483870967742dppx),
(resolution: 2.0689655172413794dppx),
(resolution: 2.00dppx),
(resolution: 2.2222222222222223dppx),
(resolution: 2.4dppx),
(resolution: 2.50dppx),
(resolution: 2.727272727272727dppx),
(resolution: 2.857142857142857dppx),
(resolution: 2.857142857142857dppx),
(resolution: 3.00dppx),
(resolution: 3.1578947368421053dppx),
(resolution: 3.3333333333333335dppx),
(resolution: 3.5294117647058822dppx),
(resolution: 3.3333333333333335dppx),
(resolution: 3.5294117647058822dppx), /* twice ?! */
(resolution: 3.75dppx),
(resolution: 4.00dppx),
(resolution: 4.285714285714286dppx),
(resolution: 4.615384615384615dppx)
{
	html>body>img:only-child:not([width]):not([height]) {
		image-rendering: var(--image-rendering, -moz-crisp-edges);
		transform: scale(calc(var(--scale-to) / var(--dppx)));
		transform-origin: top left;
		margin: 0;
		top: auto;
		bottom: auto;
		left: auto;
		right: auto;
	}
	/*
	debug
	*/
	html::after {
		content: var(--dppx-debug) ' dppx; ' var(--zoom-debug) ' zoom; scale: ' var(--scale-to-debug) '×';
		position: fixed;
		top: 0;
		right: 0;
		color: #ccc;
		background-color: rgba(0,0,0,0.5);
		font-size: calc(1 / var(--dppx) * 1.9rem);
		/*
		this effectively cancels page zoom
		so the physical text size remains the same
		like using viewport units, but without viewport
		accessibility warning
		never ever do this
		*/
	}
}

@media (resolution: 0.75dppx) {
	:root {
		--zoom-debug: '50%';
		--dppx: 0.75;
		--dppx-debug: '0.75';
		--scale-to: 0.0625;
		--scale-to-debug: '0.0625';
		--image-rendering: auto;
	}
}

@media (resolution: 0.8955223880597015dppx) {
	:root {
		--zoom-debug: '60%';
		--dppx: 0.8955223880597015;
		--dppx-debug: '0.8955223880597015';
		--scale-to: 0.125;
		--scale-to-debug: '0.125';
		--image-rendering: auto;
	}
}

@media (resolution: 1.0526315789473684dppx) {
	:root {
		--zoom-debug: '70%';
		--dppx: 1.0526315789473684;
		--dppx-debug: '1.0526315789473684';
		--scale-to: 0.25;
		--scale-to-debug: '0.25';
		--image-rendering: auto;
	}
}

@media (resolution: 1.2dppx) {
	:root {
		--zoom-debug: '80%';
		--dppx: 1.2;
		--dppx-debug: '1.2';
		--scale-to: 0.5;
		--scale-to-debug: '0.5';
		--image-rendering: auto;
	}
}

@media (resolution: 1.2dppx) {
	:root {
		--zoom-debug: '80%';
		--dppx: 1.2;
		--dppx-debug: '1.2';
		--scale-to: 0.5;
		--scale-to-debug: '0.5';
		--image-rendering: auto;
	}
}

@media (resolution: 1.3636363636363635dppx) {
	:root {
		--zoom-debug: '90%';
		--dppx: 1.3636363636363635;
		--dppx-debug: '1.3636363636363635';
		--scale-to: 1;
		--scale-to-debug: '1';
	}
}

@media (resolution: 1.50dppx) {
	:root {
		--zoom-debug: '100%';
		--dppx: 1.50;
		--dppx-debug: '1.50';
		--scale-to: 2;
		--scale-to-debug: '2';
	}
}

@media (resolution: 1.6666666666666667dppx) {
	:root {
		--zoom-debug: '110%';
		--dppx: 1.6666666666666667;
		--dppx-debug: '1.6666666666666667';
		--scale-to: 3;
		--scale-to-debug: '3';
	}
}

@media (resolution: 1.8181818181818181dppx) {
	:root {
		--zoom-debug: '120%';
		--dppx: 1.8181818181818181;
		--dppx-debug: '1.8181818181818181';
		--scale-to: 4;
		--scale-to-debug: '4';
	}
}

@media (resolution: 1.935483870967742dppx) {
	:root {
		--zoom-debug: '130%';
		--dppx: 1.935483870967742;
		--dppx-debug: '1.935483870967742';
		--scale-to: 5;
		--scale-to-debug: '5';
	}
}

@media (resolution: 2.00dppx) {
	:root {
		--zoom-debug: '133%';
		--dppx: 2.00;
		--dppx-debug: '2.00';
		--scale-to: 6;
		--scale-to-debug: '6';
	}
}

@media (resolution: 2.0689655172413794dppx) {
	:root {
		--zoom-debug: '140%';
		--dppx: 2.0689655172413794;
		--dppx-debug: '2.0689655172413794';
		--scale-to: 7;
		--scale-to-debug: '7';
	}
}

@media (resolution: 2.2222222222222223dppx) {
	:root {
		--zoom-debug: '150%';
		--dppx: 2.2222222222222223;
		--dppx-debug: '2.2222222222222223';
		--scale-to: 8;
		--scale-to-debug: '8';
	}
}

@media (resolution: 2.4dppx) {
	:root {
		--zoom-debug: '160%';
		--dppx: 2.4;
		--dppx-debug: '2.4';
		--scale-to: 9;
		--scale-to-debug: '9';
	}
}

@media (resolution: 2.50dppx) {
	:root {
		--zoom-debug: '170%';
		--dppx: 2.50;
		--dppx-debug: '2.50';
		--scale-to: 10;
		--scale-to-debug: '10';
	}
}

@media (resolution: 2.727272727272727dppx) {
	:root {
		--zoom-debug: '180%';
		--dppx: 2.727272727272727;
		--dppx-debug: '2.727272727272727';
		--scale-to: 11;
		--scale-to-debug: '11';
	}
}

@media (resolution: 2.857142857142857dppx) {
	:root {
		--zoom-debug: '190%';
		--dppx: 2.857142857142857;
		--dppx-debug: '2.857142857142857';
		--scale-to: 12;
		--scale-to-debug: '12';
	}
}

@media (resolution: 3.00dppx) {
	:root {
		--zoom-debug: '200%';
		--dppx: 3.00;
		--dppx-debug: '3.00';
		--scale-to: 13;
		--scale-to-debug: '13';
	}
}

@media (resolution: 3.1578947368421053dppx) {
	:root {
		--zoom-debug: '210%';
		--dppx: 3.1578947368421053;
		--dppx-debug: '3.1578947368421053';
		--scale-to: 14;
		--scale-to-debug: '14';
	}
}

@media (resolution: 3.3333333333333335dppx) {
	:root {
		--zoom-debug: '220%';
		--dppx: 3.3333333333333335;
		--dppx-debug: '3.3333333333333335';
		--scale-to: 15;
		--scale-to-debug: '15';
	}
}

@media (resolution: 3.5294117647058822dppx) {
	:root {
		--zoom-debug: '230% or 240%';
/*
for some mysterious reason both zoom levels matches this resolution
*/
		--dppx: 3.5294117647058822;
		--dppx-debug: '3.5294117647058822';
		--scale-to: 16;
		--scale-to-debug: '16';
	}
}

@media (resolution: 3.75dppx) {
	:root {
		--zoom-debug: '250%';
		--dppx: 3.75;
		--dppx-debug: '3.75';
		--scale-to: 17;
		--scale-to-debug: '17';
	}
}

@media (resolution: 4.00dppx) {
	:root {
		--zoom-debug: '260% or 270%';
/*
for some mysterious reason both zoom levels matches this resolution
*/
		--dppx: 4.00;
		--dppx-debug: '4.00';
		--scale-to: 18;
		--scale-to-debug: '18';
	}
}

@media (resolution: 4.285714285714286dppx) {
	:root {
		--zoom-debug: '280% or 290%';
/*
for some mysterious reason both zoom levels matches this resolution
*/
		--dppx: 4.285714285714286;
		--dppx-debug: '4.285714285714286';
		--scale-to: 19;
		--scale-to-debug: '19';
	}
}

@media (resolution: 4.615384615384615dppx) {
	:root {
		--zoom-debug: '300%';
		--dppx: 4.615384615384615;
		--dppx-debug: '4.615384615384615';
		--scale-to: 20;
		--scale-to-debug: '20';
	}
}
}