-
Notifications
You must be signed in to change notification settings - Fork 26.1k
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
<Image /> placeholder image appears "washed out" due to feathered edges #52548
Labels
bug
Issue was opened via the bug report template.
Image (next/image)
Related to Next.js Image Optimization.
locked
Comments
github-actions
bot
added
the
Image (next/image)
Related to Next.js Image Optimization.
label
Jul 11, 2023
styfle
added a commit
that referenced
this issue
Jul 26, 2023
Fixes #52548 This PR fixes the issue of the `<Image />` "blur" placeholder where the placeholder image appears "washed out" and feathered around the edges. The fix does NOT involve any API changes - only the underlying SVG filter is updated. The filter works for any image type (JPEG, GIF, WEBP) no matter if it contains transparency or not. ## How it works ```html <filter id='b' color-interpolation-filters='sRGB'> <feMorphology in='SourceAlpha' operator='dilate' radius='15' result='dilate' /> <feGaussianBlur in='dilate' stdDeviation='15' result='mask' /> <feGaussianBlur in='SourceGraphic' stdDeviation='20' result='blur' /> <feComponentTransfer in='blur' result='solid'> <feFuncA type='table' tableValues='1 1' /> </feComponentTransfer> <feComposite in2='mask' in='solid' operator='in' result="comp" /> <feMerge> <feMergeNode in="SourceGraphic" /> <feMergeNode in="comp" /> </feMerge> </filter> ``` Currently the underlying filter uses `feComponentTransfer ` to get rid of the feathered edges but only for JPEG images. This is because if alpha channel was to be mapped to 1 for images with transparency in it, all of the transparent pixels would turn black (which is obviously undesirable). The way I fixed it is by creating a mask from the SourceAlpha (effectively the "shape" of the object in an image), slightly blurring it for a smoother look (feMorphology + feGaussianBlur), and then clipping the `feComponentTransfer` result to the shape of the mask (`<feComposite in2='mask' in='solid' operator='in' result="comp" />`). Then finally `feMerge` is used to stack original image and the clipping result from the previous step just to make sure that any left over artifacts from clipping are hidden. ## Result Here's a comparison between the current implementation (left column), and the filter above (right column) <img width="614" alt="Screenshot 2023-07-12 at 10 44 56" src="https://github.com/vercel/next.js/assets/28541613/afdc1f88-eb1a-4a21-a88a-06057a875e1b"> --------- Co-authored-by: Steven <steven@ceriously.com>
kwonoj
pushed a commit
that referenced
this issue
Jul 26, 2023
Fixes #52548 This PR fixes the issue of the `<Image />` "blur" placeholder where the placeholder image appears "washed out" and feathered around the edges. The fix does NOT involve any API changes - only the underlying SVG filter is updated. The filter works for any image type (JPEG, GIF, WEBP) no matter if it contains transparency or not. ## How it works ```html <filter id='b' color-interpolation-filters='sRGB'> <feMorphology in='SourceAlpha' operator='dilate' radius='15' result='dilate' /> <feGaussianBlur in='dilate' stdDeviation='15' result='mask' /> <feGaussianBlur in='SourceGraphic' stdDeviation='20' result='blur' /> <feComponentTransfer in='blur' result='solid'> <feFuncA type='table' tableValues='1 1' /> </feComponentTransfer> <feComposite in2='mask' in='solid' operator='in' result="comp" /> <feMerge> <feMergeNode in="SourceGraphic" /> <feMergeNode in="comp" /> </feMerge> </filter> ``` Currently the underlying filter uses `feComponentTransfer ` to get rid of the feathered edges but only for JPEG images. This is because if alpha channel was to be mapped to 1 for images with transparency in it, all of the transparent pixels would turn black (which is obviously undesirable). The way I fixed it is by creating a mask from the SourceAlpha (effectively the "shape" of the object in an image), slightly blurring it for a smoother look (feMorphology + feGaussianBlur), and then clipping the `feComponentTransfer` result to the shape of the mask (`<feComposite in2='mask' in='solid' operator='in' result="comp" />`). Then finally `feMerge` is used to stack original image and the clipping result from the previous step just to make sure that any left over artifacts from clipping are hidden. ## Result Here's a comparison between the current implementation (left column), and the filter above (right column) <img width="614" alt="Screenshot 2023-07-12 at 10 44 56" src="https://github.com/vercel/next.js/assets/28541613/afdc1f88-eb1a-4a21-a88a-06057a875e1b"> --------- Co-authored-by: Steven <steven@ceriously.com>
rfearing
pushed a commit
to rfearing/next.js
that referenced
this issue
Jul 26, 2023
Fixes vercel#52548 This PR fixes the issue of the `<Image />` "blur" placeholder where the placeholder image appears "washed out" and feathered around the edges. The fix does NOT involve any API changes - only the underlying SVG filter is updated. The filter works for any image type (JPEG, GIF, WEBP) no matter if it contains transparency or not. ## How it works ```html <filter id='b' color-interpolation-filters='sRGB'> <feMorphology in='SourceAlpha' operator='dilate' radius='15' result='dilate' /> <feGaussianBlur in='dilate' stdDeviation='15' result='mask' /> <feGaussianBlur in='SourceGraphic' stdDeviation='20' result='blur' /> <feComponentTransfer in='blur' result='solid'> <feFuncA type='table' tableValues='1 1' /> </feComponentTransfer> <feComposite in2='mask' in='solid' operator='in' result="comp" /> <feMerge> <feMergeNode in="SourceGraphic" /> <feMergeNode in="comp" /> </feMerge> </filter> ``` Currently the underlying filter uses `feComponentTransfer ` to get rid of the feathered edges but only for JPEG images. This is because if alpha channel was to be mapped to 1 for images with transparency in it, all of the transparent pixels would turn black (which is obviously undesirable). The way I fixed it is by creating a mask from the SourceAlpha (effectively the "shape" of the object in an image), slightly blurring it for a smoother look (feMorphology + feGaussianBlur), and then clipping the `feComponentTransfer` result to the shape of the mask (`<feComposite in2='mask' in='solid' operator='in' result="comp" />`). Then finally `feMerge` is used to stack original image and the clipping result from the previous step just to make sure that any left over artifacts from clipping are hidden. ## Result Here's a comparison between the current implementation (left column), and the filter above (right column) <img width="614" alt="Screenshot 2023-07-12 at 10 44 56" src="https://github.com/vercel/next.js/assets/28541613/afdc1f88-eb1a-4a21-a88a-06057a875e1b"> --------- Co-authored-by: Steven <steven@ceriously.com>
Strift
pushed a commit
to Strift/next.js
that referenced
this issue
Jul 27, 2023
Fixes vercel#52548 This PR fixes the issue of the `<Image />` "blur" placeholder where the placeholder image appears "washed out" and feathered around the edges. The fix does NOT involve any API changes - only the underlying SVG filter is updated. The filter works for any image type (JPEG, GIF, WEBP) no matter if it contains transparency or not. ## How it works ```html <filter id='b' color-interpolation-filters='sRGB'> <feMorphology in='SourceAlpha' operator='dilate' radius='15' result='dilate' /> <feGaussianBlur in='dilate' stdDeviation='15' result='mask' /> <feGaussianBlur in='SourceGraphic' stdDeviation='20' result='blur' /> <feComponentTransfer in='blur' result='solid'> <feFuncA type='table' tableValues='1 1' /> </feComponentTransfer> <feComposite in2='mask' in='solid' operator='in' result="comp" /> <feMerge> <feMergeNode in="SourceGraphic" /> <feMergeNode in="comp" /> </feMerge> </filter> ``` Currently the underlying filter uses `feComponentTransfer ` to get rid of the feathered edges but only for JPEG images. This is because if alpha channel was to be mapped to 1 for images with transparency in it, all of the transparent pixels would turn black (which is obviously undesirable). The way I fixed it is by creating a mask from the SourceAlpha (effectively the "shape" of the object in an image), slightly blurring it for a smoother look (feMorphology + feGaussianBlur), and then clipping the `feComponentTransfer` result to the shape of the mask (`<feComposite in2='mask' in='solid' operator='in' result="comp" />`). Then finally `feMerge` is used to stack original image and the clipping result from the previous step just to make sure that any left over artifacts from clipping are hidden. ## Result Here's a comparison between the current implementation (left column), and the filter above (right column) <img width="614" alt="Screenshot 2023-07-12 at 10 44 56" src="https://github.com/vercel/next.js/assets/28541613/afdc1f88-eb1a-4a21-a88a-06057a875e1b"> --------- Co-authored-by: Steven <steven@ceriously.com>
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
bug
Issue was opened via the bug report template.
Image (next/image)
Related to Next.js Image Optimization.
locked
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.5.0: Mon Apr 24 20:53:19 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6020 Binaries: Node: 19.7.0 npm: 9.5.0 Yarn: 1.22.19 pnpm: 8.6.6 Relevant Packages: next: 13.4.10-canary.3 eslint-config-next: 13.0.4 react: 18.2.0 react-dom: 18.2.0 typescript: 4.9.3 Next.js Config: output: N/A
Which area(s) of Next.js are affected? (leave empty if unsure)
Image optimization (next/image, next/legacy/image)
Link to the code that reproduces this issue or a replay of the bug
https://codesandbox.io/p/sandbox/competent-agnesi-sw4tsq?file=%2Fpages%2Findex.tsx%3A30%2C9
To Reproduce
Describe the Bug
When placeholder image file type is different than JPEG, placeholder images have feathered / washed out edges around them:
Expected Behavior
Placeholder images should keep hard/solid edges around them no matter what type of file extensions is used for the placeholder image (JPEG, JPG, GIF, WEBP).
Here's a comparison between how it is now, and how it could be when fixed. Having hard edges around the image makes UI look crispier.
Feathered edges (current state):
Hard edges (expected):
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
The text was updated successfully, but these errors were encountered: