image-rendering "crisp-edges" vs. "pixelated"
Asked Answered
G

3

22

According to MDN the currently proposed values for the CSS image-rendering property are auto, crisp-edges and pixelated. But I can't see the difference between crisp-edges and pixelated since both are supposed to just scale up the pixels and not interpolate anything.

So where is the difference?

Genital answered 19/12, 2013 at 10:6 Comment(4)
Have you checked support in the browser/version you're using? developer.mozilla.org/en/docs/Web/CSS/… bearing in mind pixelated isnt supported at all at present?Frankfrankalmoign
Can I Use does not return any results for image-rendering. Is it even supported yet?Jowett
I didn't mean "see" literally since pixelated isn't supported in any browser yet. I'm just interested in what these properties are proposed to do.Genital
@Jowett caniuse has since added a page for image-rendering: github.com/Fyrd/caniuse/pull/864Tsuda
G
8

According to the spec, it seems that crisp-edge allows for smooth pixel-art scaling algorithms like 2xSaI and HQ2X; whereas pixelated only allows common nearest-neighbour scaling.

Gramercy answered 19/12, 2013 at 10:18 Comment(2)
That makes sense. So the current crisp-edge implementation in Firefox may change in the future whereas pixelated, once it is implemented, should produce exactly this result.Genital
This answer is wrong. As of Feb 2021 the spec changed. Also, pixelated was never limited to nearest neighborMaymaya
S
20

While @codl's answer is correct, it is incomplete. According to the spec, crisp-edges and pixelated differ in two ways, not just one.

  1. crisp-edges allows for pixel scaling algorithms that are fundamentally different from nearest-neighbor. Examples of other non-smoothing pixel scalers include the hqx family and EPX/Scale2x. However, pixelated must use nearest-neighbor or similar.

  2. crisp-edges applies to both upscaling and downscaling, whereas pixelated is only for upscaling. It uses the same algorithm as auto for downscaling.

The reason for these differences is that pixelated was designed for pixelated sprites, which are intended to be clearly pixelated even at large sizes, but crisp-edges was designed to prevent the edges of an image from becoming blurry. It is okay for a small sprite to get blurrier if scaled down, since it won't look any less pixelated than at its native size. And using a pixel-art scaling algorithm does keep crisp edges, but it also reduces piexlation, which is the opposite of what pixelated is designed for.

That said, there are currently proposed uses for pixelated that have nothing to do with sprites, but rather take advantage of the dual scaling algorithms. For example, on HiDPI screens, it is generally agreed that auto upscaling to normal DPI produces blurry icons. Using pixelated would allow icons to scale up without getting blurry, but also let them scale down normally. This allows the use of two different scaling algorithms in pure CSS without having to use JavaScript to check the size of the original image or the final display size.

Selfrealization answered 13/8, 2014 at 5:48 Comment(1)
This answer is wrong as well as out of date. The spec has changed.Maymaya
G
8

According to the spec, it seems that crisp-edge allows for smooth pixel-art scaling algorithms like 2xSaI and HQ2X; whereas pixelated only allows common nearest-neighbour scaling.

Gramercy answered 19/12, 2013 at 10:18 Comment(2)
That makes sense. So the current crisp-edge implementation in Firefox may change in the future whereas pixelated, once it is implemented, should produce exactly this result.Genital
This answer is wrong. As of Feb 2021 the spec changed. Also, pixelated was never limited to nearest neighborMaymaya
M
7

The spec changed in Feb 2021.

crisp-edges now means "use nearest neighbor" and pixelated means "keep it looking pixelated" which can be translated as "if you want to then do something better than nearest neighbor that keeps the image pixelated".

The current reality (2022) is, crisp-edges (only implemented in Firefox) and pixelated (implemented in Chrome/Edge and Safari) are actually implemented as nearest neighbor filtering.

But a functional note: if you have an image you're trying to scale up using image-rendering: crisp-edges your users may not be getting the result you expect. The problem is, CSS works in CSS pixels. CSS pixels are translated to device pixels. The translation from CSS pixels to device pixels is called the devicePixelRatio. The devicePixelRatio can be a non integer value.

So, for example, you have 128x128 pixel image that you want scaled to 256x256 with image-rendering: pixelated like this

<img src="128x128.png" style="width: 256px; height: 256px; image-rendering: pixelated">

and you think the user will see each pixel of the original image scaled to 2x2.

But, the user's devicePixelRatio might not be an integer. My desktop's devicePixelRatio is 1.25 which means asking for a style of width: 256px; height: 256px; ends up making a 320x320 device rectangle. The 128x128.png will be scaled to 320x320 which, with image-rendering: pixelated, when implemented as nearest-neighbor means some pixels are going to get scaled to 2x2 and others 1x1.

You can see an example here. Here's a 64x64.png

And here's 4 ways of scaling it 2x to 128x128

  1. the default (image-rendering: smooth)
  2. image-rendering: pixelated
  3. image-rendering: crisp-edges
  4. offline scaling to 256x256 then scaled back to 128x128 using the default (image-rendering: smooth)

.inline {
  display: inline-block;
  border: 1px solid red;
  text-align: center;
  padding: 10px;
}
<div class="inline">
  <img src="https://i.sstatic.net/akzX9.png"
       style="width: 128px; height: 128px;">
  <div>smooth up</div>
</div>

<div class="inline">
  <img src="https://i.sstatic.net/akzX9.png"
       style="width: 128px; height: 128px; image-rendering: pixelated">
  <div>pixelated up</div>
</div>

<div class="inline">
  <img src="https://i.sstatic.net/akzX9.png"
       style="width: 128px; height: 128px; image-rendering: crisp-edges">
  <div>crisp up</div>
</div>

<div class="inline">
  <img src="https://i.imgur.com/aahR6GT.png"
       style="width: 128px; height: 128px;">
  <div>smooth down</div>
</div>

<p>zoom in/out with Ctrl/Cmd +/-</p>

If you run the snippet and then zoom in your browser (Ctrl/Cmd +/-), at least on my machines the first 2 look much worse than the last one.

Also here's a library to scale in JavaScript which makes image-rendering: pixelated/crisp-edges more useful by making sure the image is always scaled to a multiple of device pixels.

Maymaya answered 12/6, 2022 at 22:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.