Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ideas for future improvements #4

Open
andrewstephens75 opened this issue Dec 20, 2022 · 6 comments
Open

Ideas for future improvements #4

andrewstephens75 opened this issue Dec 20, 2022 · 6 comments
Assignees

Comments

@andrewstephens75
Copy link
Owner

andrewstephens75 commented Dec 20, 2022

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 andrewstephens75 self-assigned this Dec 20, 2022
@andrewstephens75
Copy link
Owner Author

Updated the list to reflect the changes in version2

@FrostKiwi
Copy link

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.

@andrewstephens75
Copy link
Owner Author

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.

@farant
Copy link

farant commented Feb 16, 2023

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!

@9am
Copy link

9am commented Apr 23, 2023

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?

@andrewstephens75
Copy link
Owner Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants