RyotaUshio / obsidian-pdf-plus

The most Obsidian-native PDF annotation, viewing & editing tool ever. Comes with optional Vim keybindings.
https://ryotaushio.github.io/obsidian-pdf-plus/
MIT License
473 stars 11 forks source link

[FR] DPI/scale parameter option #97

Open nidhoggr-nil opened 3 months ago

nidhoggr-nil commented 3 months ago

Describe your request

Hey, would be awesome if you could add a scale/dpi option which would adjust the resolution of the built-in render in the pdf JavaScript pdf.js library.

I have earlier experimented with this, but never found a solution which could monkeypatch the built-in viewer, instead of bundling a whole new one, and then I just didn't get around to further trying to monkeypatch it after I banged my head into a wall too much 🙃

The blurriness of pdfs (which some people experience (me)) can be completely removed by changing a parameter given to the pdf object from the PDFJS.getDocument library. When calling getViewport in pdf.js, this can be adjusted as part of its parameters. I.e. const viewport = pdfPage.getViewport({ scale: 4.0 });

It's then a question of finding the correct pdf object inside obsidian ('ve mangled it quite a lot without luck, but it looks like you've got a lot of experience with doing exactly that), and hopefully once you have access it would be easy to change it (I hope).

Kind Regards

RyotaUshio commented 3 months ago

I guess PDF.js already has a mechanism for avoiding such blurring.

The resolution of the rendered PDF is determined by this class: https://github.com/mozilla/pdf.js/blob/b14f6960710127adccba3a5fca5906c333259da5/web/ui_utils.js#L82 In Obsidian, this class lives in lib/pdfjs/pdf.viewer.min.js.

This class uses window.devicePixelRatio to get an appropriate scale value so that the PDF won't be blurred. From the MDN docs:

A value of 1 indicates a classic 96 DPI display, while a value of 2 is expected for HiDPI/Retina displays.


So I'd suggest checking your window.devicePixelRatio value. If it's unexpectedly low, then you might be able to increase the resolution by just setting window.devicePixelRatio to a higher value (it's hacky, though). For example:

https://github.com/RyotaUshio/obsidian-pdf-plus/assets/72342591/c7722e2e-5095-48a2-8477-5b310eea0fb2

RyotaUshio commented 3 months ago

You can see a simplified example of how window.devicePixelRatio is used here: https://mozilla.github.io/pdf.js/examples/#rendering-the-page

You also might be interested in this example from the MDN docs: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#correcting_resolution_in_a_canvas


In addition to the canvas renderer, the text layer builder also uses devicePixelRatio, so it looks like the resolution can be controlled properly only by changing window.devicePixelRatio.

https://github.com/mozilla/pdfjs-dist/blob/5f07d5a4159bb99eee2f6143d1297f03b45bba58/lib/web/text_layer_builder.js#L64

That said, it's obviously not desirable to add an option to change window.devicePixelRatio to this plugin. So one of the possible quick fixes would be to create a Templater startup script that sets a proper devicePixelRatio value. But be careful because it will also affect other things like the graph view. Also devicePixelRatio is something that should be updated when you zoom in/out so it's really no more than a quick fix, unfortunately.

nidhoggr-nil commented 3 months ago

Thank you so much for the feedback! I'm not a javascript dev by any means, but I don't mind opening up stuff and reading whatever languages. I asked around on obsidian forums and the dev discord for obsidian, and no one could answer this back then.

Setting the devicePixelRatio worked wonderfully! It is thankfully persistent across zooms, but since you said it might not be, I'm a bit afraid of what conditions can change it, since my knowledge is limited for the domain in which javascript itself runs.

I'm off to make a quick obsidian plugin, hope I can either use the provided method in the example you gave, via a media query to track changes on the browsers own terms / lifecycle methods. Otherwise it's either monkeypatching the setter, or in the worse/hackiest scenario, making a timer to check if it needs to be changed.

N3C2L commented 2 months ago

@RyotaUshio

Many thanks for the Templater startup script you provided here: https://github.com/RyotaUshio/obsidian-pdf-plus/discussions/145#discussioncomment-9084692 It's very useful because it's enhancing the workflow for often used formats.

So one of the possible quick fixes would be to create a Templater startup script that sets a proper devicePixelRatio value.

I would be happy if you could provide us another Templater startup script that people can use for a fixed devicePixelRatio. I need a value of 2.4 hence my testing in the console.

RyotaUshio commented 2 months ago

@N3C2L I guess just <%* window.devicePixelRatio = 2.4 %> would work. <%* window.devicePixelRatio = window.devicePixelRatio || 2.4 %> will set the value only if window.devicePixelRatio is not present.

But again, I'm not sure what kind of problem can occur due to a manually fixed devicePixelRatio. For example, the graph view may crash if it's set too high (2.4 will be totally fine though).

N3C2L commented 2 months ago

Works flawless, thanks again!

RyotaUshio commented 1 month ago

Hey everyone, I noticed the official forum has a bug report thread for this exact problem, and WhiteNoise from the Obsidian team wants to hear your voice:

https://forum.obsidian.md/t/blurry-pdfs/66289/24

Rumrie commented 1 month ago

Thanks for the fix.

Guys, how can I save changes in Obs source code? It overwrites every time I leave dev console(I pressed Ctrl+S)

I'm a beginner. Sorry about stupid question