HackerTrans
TopNewTrendsCommentsPastAskShowJobs

simoneamico

no profile record

Submissions

Show HN: Veil – Dark mode PDFs without destroying images, runs in the browser

veil.simoneamico.com
100 points·by simoneamico·4개월 전·29 comments

comments

simoneamico
·3개월 전·discuss
Fixed. Full details in the commit here: https://github.com/simoneamico-ux-dev/veil/commit/9d09d9c

In short, by checking 3 simple signals veil can now distinguish a scan with overlaid OCR text from a native PDF with images. The first is whether the image covers more than 40% of the page, meaning it dominates the surface. The second is whether there are more than 200 characters, enough to be a document and not just a cover. The third is whether the image is predominantly blank paper rather than a photograph, verified by sampling the luminance of the pixels. When all three conditions are true, the image is no longer protected and the inversion applies normally. The same detection runs in the export path too. Thanks again for the file, importjelly.
simoneamico
·4개월 전·discuss
Thanks, glad it's helping your eyes!
simoneamico
·4개월 전·discuss
I come from that world myself, my first iPod Touch 4G jailbroken with Cydia at age 9 is what got me interested in how things work under the hood. So the question makes me smile. I've never tested on e-Ink. What I can tell you is that from a computer you can export the dark PDF by clicking the download icon in the toolbar, the file is a standard PDF you can send to any device. If you try it let me know how it turns out, I'm curious to see the result on a reflective display.
simoneamico
·4개월 전·discuss
Thanks, I deeply agree. It's Alan Cooper's concept in About Face, where he says that to design well you need to take the role of the apprentice alongside the master, meaning observe how they work, understand their frustrations before proposing solutions. In my case I was the master and the apprentice at the same time, but it's an approach I want to carry with me.
simoneamico
·4개월 전·discuss
Thanks for the report, you found a real bug. That document is a scan processed with Adobe Paper Capture, which adds an invisible OCR text layer on top of the scanned image. Veil sees that text and treats the PDF as native, so it protects the image from inversion instead of inverting it. The dark border you see is the PDF background margin between the page edge and where the raster image starts, that margin gets inverted by the CSS. I'll probably need to cross the text detection with image coverage, meaning that if there's an image covering almost the entire page, it's a scan even if it has native text. Thanks for the specific document, it'll be very useful for reproducing the issue.
simoneamico
·4개월 전·discuss
Thanks! Couldn't agree more
simoneamico
·4개월 전·discuss
Thanks, really appreciate it. Hearing that it solves a real problem means a lot to me. Running locally is definitely about privacy, but it partly comes from my past working in a factory where the network was unreliable, so I was basically forced to build tools that worked offline. Knowing that habit is appreciated fills me with joy.
simoneamico
·4개월 전·discuss
Thanks! I'm curious to see how the comparison goes, especially on papers with lots of images and color charts. Let me know how it goes
simoneamico
·4개월 전·discuss
This means a lot, thank you. "The original vision for apps" is exactly the philosophy I built it with. I invested a lot in the service worker and iOS rendering (smaller canvas pool, DPR capped at 2, periodic engine reset to stay under Jetsam's memory limits), so hearing that the experience holds up in real use is the most valuable feedback I could get. iOS was the hardest platform to optimize, glad to know it was worth it. If you notice anything that doesn't work well on longer documents, let me know.
simoneamico
·4개월 전·discuss
It's not resistance toward AI. Machine learning isn't among my current skills and I preferred to build with tools I could maintain and debug on my own, but the door isn't closed. Thank you for pushing on this point.
simoneamico
·4개월 전·discuss
Really appreciate this AbanoubRodolf, thank you. The brightness analysis code and the image bounds are both already in the project, I just never connected the two. The distance between where I am and where you're suggesting I go is really short. Feedback like this is exactly why I posted here. Thanks again
simoneamico
·4개월 전·discuss
Actually, raster images are never inverted, they're protected. The CSS filter: invert() hits the entire canvas (text and images together), then the overlay paints the original image pixels back on top, restoring them. The result is: inverted text, images with their original colors.

The choice to never invert raster images isn't a compromise, it's the design decision. The problem veil solves is exactly that: every dark mode reader today inverts everything, and the result on photos, histology, color charts, scans is unusable. Preserving all images is the conservative choice, and for my target (people reading scientific papers, medical reports, technical manuals) it's the right one.

It's absolutely true that there's a subset of raster images, like diagrams with white backgrounds and black lines, that would benefit from inversion. I could be wrong, but in my experience they're a minority, and the cost of accidentally inverting the wrong one (a medical photo, a color chart) is much higher than the benefit of inverting a black and white diagram, from my point of view. For now the per-page toggle covers those cases.
simoneamico
·4개월 전·discuss
That really means a lot, ainch. I hope it makes your late-night sessions a little more bearable. If you find anything that doesn't work well with the papers you read, keep me posted
simoneamico
·4개월 전·discuss
That's actually exactly where I started. The initial idea involved a YOLO nano model to classify images, deciding what to invert and what not to. It worked as a concept, but during the feasibility analysis I realized that for native PDFs it wasn't necessary: the format already tells you where the images are. I walk the page's operator list via getOperatorList() (PDF.js public API, no fork) and reconstruct the CTM stack, that is the save, restore and transform operations, until I hit a paintImageXObject. The current transformation matrix gives me the exact bounds. I copy those pixels from a clean render onto an overlay canvas with no filters, and the images stay intact. It's just arithmetic on transformation matrices, on a typical page it takes a few milliseconds.

Your approach with a classifier makes a lot more sense for the generic web, where you're dealing with arbitrary <img> tags with no structural metadata, and there you have no choice but to look at what's inside. PDFs are a more favorable problem.

A case where a classifier like yours would be an interesting complement is purely vector diagrams, drawn with PDF path operators, not raster images. Veil inverts those along with the text because from the format's perspective they're indistinguishable. In practice they're rare enough that the per-page toggle handles them, but it's the honest limitation of the approach.