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

Next/future/image blur placeholder renders with visual artifacts #40419

Closed
1 task done
iominh opened this issue Sep 10, 2022 · 3 comments · Fixed by #41573
Closed
1 task done

Next/future/image blur placeholder renders with visual artifacts #40419

iominh opened this issue Sep 10, 2022 · 3 comments · Fixed by #41573
Assignees
Labels
Image (next/image) Related to Next.js Image Optimization.

Comments

@iominh
Copy link

iominh commented Sep 10, 2022

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000
Binaries:
  Node: 16.16.0
  npm: 8.11.0
  Yarn: 1.22.19
  pnpm: N/A
Relevant packages:
  next: 12.3.0
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0

What browser are you using? (if relevant)

Chrome 105.0.5195.102

How are you deploying your application? (if relevant)

Vercel and Linode (occurs in all environments)

Describe the Bug

When using the Image component from next/future/image with a blur placeholder and base64 blurDataURL, the placeholder renders in Chrome 105.0.5195.102 with visual artifacts, likely because the placeholder is being requested with a different request URL (i.e. we specified a data:image/jpeg; but the placeholder in the browser is being requested as data:image/svg+xml with an svg filter applied

I deployed an example to https://nextjs-next-image-issue.vercel.app/ and https://github.com/iominh/nextjs-next-image-issue.

It might be hard to see the blur placeholder but if you use the chrome devtools to apply heavy throttling (e.g. with 3g) and/or just look at the devtools you'll see the placeholder is loaded incorrectly with visual artifacts and the wrong requestURL

Here's an example based on Next 12.3.0 and React 18.2.0:

import type { NextPage } from "next";
import Head from "next/head";
import Image from "next/future/image";
import styles from "../styles/Home.module.css";

// Sample blur
export const blurDataURL =
  "data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAIRAAAQMEAQUAAAAAAAAAAAAAAQACAwQFCBETITJEUdL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABoRAQEAAgMAAAAAAAAAAAAAAAECABIEMUH/2gAMAwEAAhEDEQA/AJLRkG+kgbELPTyxcXQOlc0k++0rKkyA3I4mxU+yT5DvhEVZrIqHeFxx4p1fM//Z";

const Home: NextPage = () => {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <div className={styles.description}>
          The below image should blur without visual artifacts
        </div>
        <Image
          src="/tuqa-nabi-uhnZZUaTIOs-unsplash.jpg"
          alt="Kitten"
          width={2848}
          height={4288}
          placeholder="blur"
          blurDataURL={blurDataURL}
        ></Image>
     
      </main>
    </div>
  );
};

export default Home;

In the chrome dev tools you can see the placeholder renders like the following:

image

Expected Behavior

I would've expected the placeholder to render without artifacts and with the correct type

Before next/future/image, the next/image component would return a placeholder like the following:

data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAIRAAAQMEAQUAAAAAAAAAAAAAAQACAwQFCBETITJEUdL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABoRAQEAAgMAAAAAAAAAAAAAAAECABIEMUH/2gAMAwEAAhEDEQA/AJLRkG+kgbELPTyxcXQOlc0k++0rKkyA3I4mxU+yT5DvhEVZrIqHeFxx4p1fM//Z

Instead it now returns the following:

data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 2400 1601'%3E%3Cfilter id='b' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1'/%3E%3C/feComponentTransfer%3E%%3C/filter%3E%3Cimage filter='url(%23b)' x='0' y='0' height='100%25' width='100%25' href='data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAIRAAAQMEAQUAAAAAAAAAAAAAAQACAwQFCBETITJEUdL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABoRAQEAAgMAAAAAAAAAAAAAAAECABIEMUH/2gAMAwEAAhEDEQA/AJLRkG+kgbELPTyxcXQOlc0k++0rKkyA3I4mxU+yT5DvhEVZrIqHeFxx4p1fM//Z'/%3E%3C/svg%3E

Link to reproduction

https://nextjs-next-image-issue.vercel.app/, https://github.com/iominh/nextjs-next-image-issue

To Reproduce

Go to https://nextjs-next-image-issue.vercel.app/ to see the placeholder load or create an image like shown in the description above

@iominh iominh added the bug Issue was opened via the bug report template. label Sep 10, 2022
@iominh iominh changed the title Next/future/image blurDataURL shows Next/future/image blur placeholder renders with visual artifacts Sep 10, 2022
@balazsorban44 balazsorban44 added the Image (next/image) Related to Next.js Image Optimization. label Sep 10, 2022
@menberg
Copy link

menberg commented Oct 1, 2022

Same happens on Safari. The problem appears if the aspect ratio of the placeholder is different from the ratio of the displayed image.

@styfle
Copy link
Member

styfle commented Oct 19, 2022

Thanks for reporting!

This issue is likely caused by the aspect ratio of the of the provided blurDataURL doesn't match the aspect ratio provided by width and height.

  • 10 / 7 = 1.428
  • 2848 / 4288 = 0.66

I believe we can fix the artifacts with preserveAspectRatio="none" (I'll make a PR) but it might not lead the to result you expect, so I recommend changing the blur placeholder to match the aspect ratio of the original image.

@styfle styfle self-assigned this Oct 19, 2022
@styfle styfle added kind: bug and removed bug Issue was opened via the bug report template. labels Oct 19, 2022
ijjk pushed a commit that referenced this issue Oct 19, 2022
This PR fixes two bugs:

- Fixes #40419 
- Fixes #41393 

The first is when the aspect ratio of the `width` and `height` does not
match the aspect ratio of the `blurDataURL` provided. This can result in
artifacts around the edges. The solution is to add
`preserveAspectRatio="none"`.

The second is when there is no `width` or `height` provided (which is
normal when using `fill`) so the viewBox was undefined. This can also
cause artifacts around the edges. The solution is to change the blur
technique from gaussian to css filter, similar to `next/legacy/image`.

Note: css blur might be [slower in
firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=925025) which is
why we'll only use it for this corner case.
Kikobeats pushed a commit to Kikobeats/next.js that referenced this issue Oct 24, 2022
This PR fixes two bugs:

- Fixes vercel#40419 
- Fixes vercel#41393 

The first is when the aspect ratio of the `width` and `height` does not
match the aspect ratio of the `blurDataURL` provided. This can result in
artifacts around the edges. The solution is to add
`preserveAspectRatio="none"`.

The second is when there is no `width` or `height` provided (which is
normal when using `fill`) so the viewBox was undefined. This can also
cause artifacts around the edges. The solution is to change the blur
technique from gaussian to css filter, similar to `next/legacy/image`.

Note: css blur might be [slower in
firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=925025) which is
why we'll only use it for this corner case.
@github-actions
Copy link
Contributor

github-actions bot commented Dec 6, 2022

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Image (next/image) Related to Next.js Image Optimization.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants