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

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

目前為 2020-06-17 提交的版本,檢視 最新版本

  1. /* ==UserStyle==
  2. @name Crisp up-scaled images for displays with 150% DPI scale factor (Firefox 74+)
  3. @description Prevents blurry anti-aliased borders between picture sampling areas ("pixels").
  4. @namespace myfonj
  5. @version 1.0.1
  6. @license CC0 - Public Domain
  7. ==/UserStyle== */
  8.  
  9. @-moz-document regexp(".*\\.(png|gif)(\\?.*)?(#.*)?$") {
  10. /*
  11. "DPI Zoom (scale) factor" can be obtained with JavaScript:
  12.  
  13. window.devicePixelRatio
  14.  
  15. for 150% DPI scale factor at page with 100% zoom level this should be 1.5
  16.  
  17. min zoom is 30 %
  18. max zoom is 300 %
  19.  
  20. [ctrl] + [mouse wheel] modifies DPI consistently by +- 10 %.
  21.  
  22. [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.
  23.  
  24. [1] in theory combining wheel and keyboard zoom one could possibly get 30, *33*, *37*, 40, *43*, *47*, 50 (...) zoom factors.
  25.  
  26. a.k.a. resolution value for media query
  27. this file expects "normal" scale factor to be *150%*
  28. what normally causes ugly blurry "scaled down" images
  29. this style undoes that scale so that image pixels are mapped to physical pixels and anti-aliasing is suppressed
  30. 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.
  31. */
  32.  
  33.  
  34. /*
  35. 100% page zoom
  36. 1 = __ monitor scale × __ transform scale to "undo"
  37. 1 = 1.25 × 0.8
  38. 1 = 1.5 × 0.6666666666666
  39. 1 = 2 × 0.5
  40. strangemesses:
  41. ?? __ page zoom at monitor set to __ scale is matched by `(resolution: __)`
  42. !! 90% 100% 0.895522445440292259dppx
  43. OK 50% 100% 0.5dppx
  44. OK 100% 125% 1.25dppx
  45. !! 100% 175% 1.76470595598220835dppx
  46.  
  47. centering crisp image of odd dimesion would produce unwanted "notch" from rounding
  48. drawbacks:
  49. - zooming is funky: apparently "zoom" is done by ajdusting DPI factor, so sometimes some of our rules hits
  50.  
  51. [width][height] = image fits viewport
  52. */
  53.  
  54.  
  55. @media
  56. (resolution: 0.75dppx),
  57. (resolution: 0.8955223880597015dppx),
  58. (resolution: 1.0526315789473684dppx),
  59. (resolution: 1.2dppx),
  60. (resolution: 1.3636363636363635dppx),
  61. (resolution: 1.50dppx),
  62. (resolution: 1.6666666666666667dppx),
  63. (resolution: 1.8181818181818181dppx),
  64. (resolution: 1.935483870967742dppx),
  65. (resolution: 2.0689655172413794dppx),
  66. (resolution: 2.00dppx),
  67. (resolution: 2.2222222222222223dppx),
  68. (resolution: 2.4dppx),
  69. (resolution: 2.50dppx),
  70. (resolution: 2.727272727272727dppx),
  71. (resolution: 2.857142857142857dppx),
  72. (resolution: 2.857142857142857dppx),
  73. (resolution: 3.00dppx),
  74. (resolution: 3.1578947368421053dppx),
  75. (resolution: 3.3333333333333335dppx),
  76. (resolution: 3.5294117647058822dppx),
  77. (resolution: 3.3333333333333335dppx),
  78. (resolution: 3.5294117647058822dppx), /* twice ?! */
  79. (resolution: 3.75dppx),
  80. (resolution: 4.00dppx),
  81. (resolution: 4.285714285714286dppx),
  82. (resolution: 4.615384615384615dppx)
  83. {
  84. html>body>img:only-child:not([width]):not([height]) {
  85. image-rendering: var(--image-rendering, -moz-crisp-edges);
  86. transform: scale(calc(var(--scale-to) / var(--dppx)));
  87. transform-origin: top left;
  88. margin: 0;
  89. top: auto;
  90. bottom: auto;
  91. left: auto;
  92. right: auto;
  93. }
  94. /*
  95. debug
  96. */
  97. html::after {
  98. content: var(--dppx-debug) ' dppx; ' var(--zoom-debug) ' zoom; scale: ' var(--scale-to-debug) '×';
  99. position: fixed;
  100. top: 0;
  101. right: 0;
  102. color: #ccc;
  103. background-color: rgba(0,0,0,0.5);
  104. font-size: calc(1 / var(--dppx) * 1.9rem);
  105. /*
  106. this effectively cancels page zoom
  107. so the physical text size remains the same
  108. like using viewport units, but without viewport
  109. accessibility warning
  110. never ever do this
  111. */
  112. }
  113. }
  114.  
  115. @media (resolution: 0.75dppx) {
  116. :root {
  117. --zoom-debug: '50%';
  118. --dppx: 0.75;
  119. --dppx-debug: '0.75';
  120. --scale-to: 0.0625;
  121. --scale-to-debug: '0.0625';
  122. --image-rendering: auto;
  123. }
  124. }
  125.  
  126. @media (resolution: 0.8955223880597015dppx) {
  127. :root {
  128. --zoom-debug: '60%';
  129. --dppx: 0.8955223880597015;
  130. --dppx-debug: '0.8955223880597015';
  131. --scale-to: 0.125;
  132. --scale-to-debug: '0.125';
  133. --image-rendering: auto;
  134. }
  135. }
  136.  
  137. @media (resolution: 1.0526315789473684dppx) {
  138. :root {
  139. --zoom-debug: '70%';
  140. --dppx: 1.0526315789473684;
  141. --dppx-debug: '1.0526315789473684';
  142. --scale-to: 0.25;
  143. --scale-to-debug: '0.25';
  144. --image-rendering: auto;
  145. }
  146. }
  147.  
  148. @media (resolution: 1.2dppx) {
  149. :root {
  150. --zoom-debug: '80%';
  151. --dppx: 1.2;
  152. --dppx-debug: '1.2';
  153. --scale-to: 0.5;
  154. --scale-to-debug: '0.5';
  155. --image-rendering: auto;
  156. }
  157. }
  158.  
  159. @media (resolution: 1.2dppx) {
  160. :root {
  161. --zoom-debug: '80%';
  162. --dppx: 1.2;
  163. --dppx-debug: '1.2';
  164. --scale-to: 0.5;
  165. --scale-to-debug: '0.5';
  166. --image-rendering: auto;
  167. }
  168. }
  169.  
  170. @media (resolution: 1.3636363636363635dppx) {
  171. :root {
  172. --zoom-debug: '90%';
  173. --dppx: 1.3636363636363635;
  174. --dppx-debug: '1.3636363636363635';
  175. --scale-to: 1;
  176. --scale-to-debug: '1';
  177. }
  178. }
  179.  
  180. @media (resolution: 1.50dppx) {
  181. :root {
  182. --zoom-debug: '100%';
  183. --dppx: 1.50;
  184. --dppx-debug: '1.50';
  185. --scale-to: 2;
  186. --scale-to-debug: '2';
  187. }
  188. }
  189.  
  190. @media (resolution: 1.6666666666666667dppx) {
  191. :root {
  192. --zoom-debug: '110%';
  193. --dppx: 1.6666666666666667;
  194. --dppx-debug: '1.6666666666666667';
  195. --scale-to: 3;
  196. --scale-to-debug: '3';
  197. }
  198. }
  199.  
  200. @media (resolution: 1.8181818181818181dppx) {
  201. :root {
  202. --zoom-debug: '120%';
  203. --dppx: 1.8181818181818181;
  204. --dppx-debug: '1.8181818181818181';
  205. --scale-to: 4;
  206. --scale-to-debug: '4';
  207. }
  208. }
  209.  
  210. @media (resolution: 1.935483870967742dppx) {
  211. :root {
  212. --zoom-debug: '130%';
  213. --dppx: 1.935483870967742;
  214. --dppx-debug: '1.935483870967742';
  215. --scale-to: 5;
  216. --scale-to-debug: '5';
  217. }
  218. }
  219.  
  220. @media (resolution: 2.00dppx) {
  221. :root {
  222. --zoom-debug: '133%';
  223. --dppx: 2.00;
  224. --dppx-debug: '2.00';
  225. --scale-to: 6;
  226. --scale-to-debug: '6';
  227. }
  228. }
  229.  
  230. @media (resolution: 2.0689655172413794dppx) {
  231. :root {
  232. --zoom-debug: '140%';
  233. --dppx: 2.0689655172413794;
  234. --dppx-debug: '2.0689655172413794';
  235. --scale-to: 7;
  236. --scale-to-debug: '7';
  237. }
  238. }
  239.  
  240. @media (resolution: 2.2222222222222223dppx) {
  241. :root {
  242. --zoom-debug: '150%';
  243. --dppx: 2.2222222222222223;
  244. --dppx-debug: '2.2222222222222223';
  245. --scale-to: 8;
  246. --scale-to-debug: '8';
  247. }
  248. }
  249.  
  250. @media (resolution: 2.4dppx) {
  251. :root {
  252. --zoom-debug: '160%';
  253. --dppx: 2.4;
  254. --dppx-debug: '2.4';
  255. --scale-to: 9;
  256. --scale-to-debug: '9';
  257. }
  258. }
  259.  
  260. @media (resolution: 2.50dppx) {
  261. :root {
  262. --zoom-debug: '170%';
  263. --dppx: 2.50;
  264. --dppx-debug: '2.50';
  265. --scale-to: 10;
  266. --scale-to-debug: '10';
  267. }
  268. }
  269.  
  270. @media (resolution: 2.727272727272727dppx) {
  271. :root {
  272. --zoom-debug: '180%';
  273. --dppx: 2.727272727272727;
  274. --dppx-debug: '2.727272727272727';
  275. --scale-to: 11;
  276. --scale-to-debug: '11';
  277. }
  278. }
  279.  
  280. @media (resolution: 2.857142857142857dppx) {
  281. :root {
  282. --zoom-debug: '190%';
  283. --dppx: 2.857142857142857;
  284. --dppx-debug: '2.857142857142857';
  285. --scale-to: 12;
  286. --scale-to-debug: '12';
  287. }
  288. }
  289.  
  290. @media (resolution: 3.00dppx) {
  291. :root {
  292. --zoom-debug: '200%';
  293. --dppx: 3.00;
  294. --dppx-debug: '3.00';
  295. --scale-to: 13;
  296. --scale-to-debug: '13';
  297. }
  298. }
  299.  
  300. @media (resolution: 3.1578947368421053dppx) {
  301. :root {
  302. --zoom-debug: '210%';
  303. --dppx: 3.1578947368421053;
  304. --dppx-debug: '3.1578947368421053';
  305. --scale-to: 14;
  306. --scale-to-debug: '14';
  307. }
  308. }
  309.  
  310. @media (resolution: 3.3333333333333335dppx) {
  311. :root {
  312. --zoom-debug: '220%';
  313. --dppx: 3.3333333333333335;
  314. --dppx-debug: '3.3333333333333335';
  315. --scale-to: 15;
  316. --scale-to-debug: '15';
  317. }
  318. }
  319.  
  320. @media (resolution: 3.5294117647058822dppx) {
  321. :root {
  322. --zoom-debug: '230% or 240%';
  323. /*
  324. for some mysterious reason both zoom levels matches this resolution
  325. */
  326. --dppx: 3.5294117647058822;
  327. --dppx-debug: '3.5294117647058822';
  328. --scale-to: 16;
  329. --scale-to-debug: '16';
  330. }
  331. }
  332.  
  333. @media (resolution: 3.75dppx) {
  334. :root {
  335. --zoom-debug: '250%';
  336. --dppx: 3.75;
  337. --dppx-debug: '3.75';
  338. --scale-to: 17;
  339. --scale-to-debug: '17';
  340. }
  341. }
  342.  
  343. @media (resolution: 4.00dppx) {
  344. :root {
  345. --zoom-debug: '260% or 270%';
  346. /*
  347. for some mysterious reason both zoom levels matches this resolution
  348. */
  349. --dppx: 4.00;
  350. --dppx-debug: '4.00';
  351. --scale-to: 18;
  352. --scale-to-debug: '18';
  353. }
  354. }
  355.  
  356. @media (resolution: 4.285714285714286dppx) {
  357. :root {
  358. --zoom-debug: '280% or 290%';
  359. /*
  360. for some mysterious reason both zoom levels matches this resolution
  361. */
  362. --dppx: 4.285714285714286;
  363. --dppx-debug: '4.285714285714286';
  364. --scale-to: 19;
  365. --scale-to-debug: '19';
  366. }
  367. }
  368.  
  369. @media (resolution: 4.615384615384615dppx) {
  370. :root {
  371. --zoom-debug: '300%';
  372. --dppx: 4.615384615384615;
  373. --dppx-debug: '4.615384615384615';
  374. --scale-to: 20;
  375. --scale-to-debug: '20';
  376. }
  377. }
  378. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址