umputun / remark42

comment engine
https://remark42.com
MIT License
4.76k stars 376 forks source link

Anonymous avatars are blurry at low DPI #1632

Open cowsay1 opened 1 year ago

cowsay1 commented 1 year ago

Identicon-generated avatars are not as pixel-perfect as they should be. This appear most distinct and annoying when viewed on a default 1080p monitor with a DPR:1 (device pixel ratio), where they like soap clouds: image (left - remark live demo, right - true 24px generated identicons )

image image copied from the remark demo (it was generated at 300px, and resized to 48px using AVATAR_RESIZE=48)

very zoomed ![image](https://user-images.githubusercontent.com/60675651/235350545-1796891f-a43b-4aef-ba0c-457d53db75ba.png)

It's broken and appears slightly anti-aliased even on high-resolution (retina or mobile), because the source image was too large. Both resizing methods, whether using browser CSS resizing or writing the resized PNG to a file, add visual smoothing, so it's not just an issue with AVATAR_RESIZE.

// GenerateAvatar for give user with identicon
func GenerateAvatar(user string) ([]byte, error) {
    // ...
    buf := &bytes.Buffer{}
    err = ii.Png(300, buf)
    return buf.Bytes(), err
}

It's hard to find a straightforward solution, as resizing an image should take into account DPI from 1 to 3. If we simply change ii.Png to 24, it will look great on fullhd but blurry on retina. On the other hand, if we generate a 72px image, it will be still bad for fullhd.

My two-step solution:

  1. Change ii.Png from 300 to the AVATAR_RESIZE value (do not hardcode it based on the default .comment__avatar 24px width/height, so that people can modify it as needed and still get properly-rendered avatars).
  2. Use the CSS trick image-rendering: pixelated, which works well for small pixel images but only for those that are small enough (it's not ideal with a 300px image resized to a 24px CSS box, but works perfectly for a 72px image resized to 24px). image (This is a 24px avatar box, with a native 72px PNG, zoomed in Photoshop)

Since image-rendering will break normal raster avatars, on the frontend side: anonymous avatars imgs (or their parent block) should be marked with a class, something like

.comment_anonymous .avatar {
    image-rendering: pixelated
}
paskal commented 1 year ago

Sounds interesting. Could you please provide a PR with these changes for a test?