13 comments

  • Tomjosetj31 4 hours ago
    "Reading in the factory the books that eventually helped me get out of it" — that's a hell of a backstory for a side project, and it shows. The best tools come from a real, specific frustration rather than a market gap someone identified on a spreadsheet. The 0.86 inversion value being tuned for hours of actual reading rather than just looking right in a demo is exactly that kind of detail.
    • simoneamico 2 hours ago
      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.
  • Terretta 20 hours ago
    This is shockingly good, even better saved to iPad Pro Home Screen as an app with beautiful UX.

    Hey, HN, look at what you don't need an App Store approval for!

    // Commenting from my iPad in dark mode, using Noir extension so HN is in dark mode, reading Shifty Shades of Grey - The different risk profiles of the dark fleet explained in dark mode in the veil pwa app, which was distributed as simply as: visit app, save to Home Screen (the original vision for apps).

    • simoneamico 7 hours ago
      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.
  • gwern 22 hours ago
    Have you considered, since you can extract the images via the mask, selectively inverting them?

    One can fairly reliably use a small NN to classify images by whether they should be inverted or just dimmed, and I've used it with great success for years now on my site: https://invertornot.com/ https://gwern.net/invertornot

    ---

    On a side note, it'd be nice to have an API or something to let one 'compile' a PDF to dark-mode version PDF. Ephemeral browser-based is a drawback as often as a benefit.

    • simoneamico 22 hours ago
      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.

      • gwern 21 hours ago
        > In practice they're rare enough that the per-page toggle handles them, but it's the honest limitation of the approach.

        I don't understand how you handle raster images. You simply cannot invert them blindly. So it sounds like you just bite the bullet of never inverting raster images, and accepting that you false-positive some vector-based diagrams? I don't see how that can justify your conclusion "it wasn't necessary". It sounds necessary to me.

        • simoneamico 21 hours ago
          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.

          • gwern 18 hours ago
            > 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.

            OK, so I did understand, but this sounds very hand wavy to me. You say it's a 'minority'; well sure, I never claimed that was >50% of images, so I suppose yes, that's technically true. And it is also true that a false positive on inverting is usually nastier than a false negative, which is why everyone defaults to dimming rather than inverting.

            But you don't sound like you have evaluated it very seriously, and at least on my part, when I browse my dark-mode Gwern.net pages, I see lots of images and diagrams which benefit from inverting and where I'm glad we have InvertOrNot.com to rely on (and it's rarely wrong).

            It may be nice to be able to advertise "No AI" at the top of the page, but I don't understand why you are so committed to biting this bullet and settling for leaving images badly handled when there is such a simple easy-to-use solution you can outsource to, and there's not a whole lot else a 'dark mode PDF' can do if 'handle images correctly' is now out of scope as acceptable collateral damage and 'meh, the user can just solve it every time they read every affected page by pushing a button'. (If Veil doesn't exist to save the user effort and bad-looking PDFs, why does it exist?)

            • simoneamico 8 hours ago
              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.
        • AbanoubRodolf 19 hours ago
          The raster image problem is real but there's a middle ground between "never invert" and a full NN classifier.

          The author already computes BT.601 brightness per page. You can run the same calculation per-image bounding box instead of per-page, then add a bimodal pixel distribution check: if a raster image has most pixels near black or near white with few midtones, it's probably a line diagram or screenshot, not a photograph. That heuristic catches the main false-positive case (black-line diagrams on white backgrounds) with maybe 20 lines of image processing code.

          It won't be perfect, and gwern's point stands that a proper trained classifier would be more accurate. But for a PDF viewer where you're already parsing content streams to get image coordinates, it's a lot cheaper than shipping a model and handles 80% of the problematic cases. The remaining edge cases (medical scans, thermal images) are rare enough that the per-page toggle is reasonable fallback.

          • simoneamico 8 hours ago
            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
          • gwern 18 hours ago
            FWIW, we did consider a histogram heuristic, and I believe GreaterWrong still uses one rather than InvertOrNot.com. But I regularly saw images on GW where the heuristic got it wrong but ION got it right, so the accuracy gap was meaningful; and that's why we went for ION rather than port over the histogram heuristic.
  • ainch 22 hours ago
    As a PhD student doing my fair share of midnight paper-reading I think I'm the exact target market - thank you for sharing!
    • simoneamico 22 hours ago
      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
  • ashton314 20 hours ago
    This is cool!

    I use Zotero [1] to manage/read/annotate all my papers and it's got a built-in PDF inverter that works pretty well. I'll take Veil out for a spin some time and see if it works well in places where Zotero's algorithm fails.

    [1]: https://zotero.org

    • simoneamico 7 hours ago
      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
  • importjelly 20 hours ago
    Doesn't work for me with this document: https://ajsonline.org/article/63137-double-star-discoveries-...

    I just get a dark border around a block of white page with black text.

    • simoneamico 7 hours ago
      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.
  • abhay_ramesh 1 hour ago
    How would it work on e-Ink Displays, can we jailbreak kindle and readers to add it like a plugin?
    • simoneamico 46 minutes ago
      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.
  • sibtain1997 11 hours ago
    This is really cool. Most dark mode tools break images, so this solves a real problem.

    I like that it runs locally too. Starred it

    • simoneamico 7 hours ago
      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.
      • sibtain1997 4 hours ago
        That's a great origin story. Constraints make better software.
  • grahammccain 9 hours ago
    Love this. Everything should be dark mode capable. Save the eyes!
  • Jasperdew 4 hours ago
    [dead]
  • AUF2026 21 hours ago
    [dead]