as-dithered-image icon indicating copy to clipboard operation
as-dithered-image copied to clipboard

Ideas for future improvements

Open andrewstephens75 opened this issue 2 years ago • 6 comments

Random ideas for the future (in no particular order)

Make sure none of these changes break printing

  • ~~add image-rendering: crisp-edges or pixilated to the canvas css~~
  • ~~have another attempt at handling fractional device pixel ratios~~
  • ~~cache the src image once, don't load it every time~~
  • ~~automatically apply the aspect ratio when the new image loads~~
  • do something if the image fails to load (show placeholder icon?)
  • ~~Move dithering to worker. Cancel outstanding operations on subsequent resizing.~~
  • ~~Try to reduce redraws during resizing - possibly defer resizing until no resize events have been seen for 10ms or something~~
  • ~~defer resizing if the component is off-screen, performing the operation just as it scrolls into view with the Intersection API : https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API~~
  • display something during resizing, a placeholder image or icon.
  • support a dither attribute to swap in alternate dithers (Sierra dithering looks interesting https://github.com/nwj/dither)
  • ~~support a threshold attribute to control the threshold between light and dark (0.0 - 1.0, 0.5 is the default)~~
  • support dark and light attributes to control the color of the resulting image. Do we dither assuming these will be black and white and then just force the color or actually dither to those colors (much harder)?
  • maybe have a setting to set one of the colors to transparent (for slightly off-white backgrounds, etc)
  • have another attempt at extending the img tag. We cannot get access to the image data but perhaps you can fetch the src and render a replacement canvas over the top.

andrewstephens75 avatar Dec 20 '22 20:12 andrewstephens75

Updated the list to reflect the changes in version2

andrewstephens75 avatar Jan 16 '23 22:01 andrewstephens75

A suggestion would be a lower bound for when dithering is applied per pixel, and instead switches to the browsers bi-linear filtering. When zoomed out the images may become unrecognizable. image There are similar approaches to some texture handling, where maximizing is done with a cubic filter, but minimizing always with a box filter to preserve sharpness. Don't recall where I have seen that though, that feature is in a similar spirit.

FrostKiwi avatar Jan 20 '23 00:01 FrostKiwi

Thanks for the report - the goal here is always to match pixel-for-pixel with each real pixel being either fully black or fully white, so I have tried to avoid bilinear filtering. I tried very hard to deal with non-integer devicePixelRatios but obviously I failed for some use cases. There really is no good solution, just workarounds.

andrewstephens75 avatar Jan 20 '23 01:01 andrewstephens75

I've used a macOS app called HyperDither, and one of the nice features is being able to control how many shades of gray are part of the final image: image

I've found the sweet spot is 3-5 shades of gray for very nice looking results.

Thank you for such a cool project!

farant avatar Feb 16 '23 13:02 farant

Nice project!! 🎉

Looking at your codes recall many fun memories building <img-victor>, which shares the many common logic of processing the imgData.

img-victor-demo-manual

Based on my experiences of building it, some suggestions:

  1. It would be nice to have a pending status before the image gets loaded and processed.
  2. Instead of creating a worker for every component constructor without terminate() them, add a workers pool to reuse feel workers. It would be a memory saver when we have a lot of <as-dithered-image> on the screen
  3. Once the image gets loaded, it will expand the height, and cause a reflow which is bad UE. And will hurt your DOM IntersectionObserver, because of the collapse of element height, some of the <as-dithered-image> that shouldn’t be on screen, are now in the viewport.

    In <img-victor>, I offer a ratio attribute which’ll create a skeleton to fill the position. If you have better ideas, please let me know.

  4. Have you considered publishing this on NPM?

9am avatar Apr 23 '23 07:04 9am

Hi 9am, thank you for your kind words. Your project looks really cool.

I considered having a pending status while the image is being processed but processing turned out to be so quick on modern machines that I thought it was better to just to get on with displaying the real image rather than flashing up a placeholder.

I am not very experienced in using workers - I'll take a look at your implementation. That said, I don't think it will make much difference unless you have a lot of dithered images on screen at the same time.

I haven't found a good way around your third point apart from forcing the user to specify the size up-front. This is supposed to be a drop-in replacement for the image tag, which works much the same way.

Finally, I figured that installing two files is not a huge burden on anyone that wants to use my project. I have another round of improvements planned when I get the time so maybe I'll change my mind then.

andrewstephens75 avatar Apr 23 '23 21:04 andrewstephens75