as-dithered-image
                                
                                
                                
                                    as-dithered-image copied to clipboard
                            
                            
                            
                        Ideas for future improvements
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.
 
Updated the list to reflect the changes in version2
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.
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.
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.
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:

I've found the sweet spot is 3-5 shades of gray for very nice looking results.
Thank you for such a cool project!
Nice project!! 🎉
Looking at your codes recall many fun memories building <img-victor>, which shares the many common logic of processing the imgData.
Based on my experiences of building it, some suggestions:
- It would be nice to have a pending status before the image gets loaded and processed.
 - 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 - Once the image gets loaded, it will expand the height, and cause a 
reflowwhich is bad UE. And will hurt your DOMIntersectionObserver, 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
ratioattribute which’ll create a skeleton to fill the position. If you have better ideas, please let me know. - Have you considered publishing this on NPM?
 
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.