我有一个简单的卡片元素,里面有一个
<img>
标签。该图像具有 object-fit: cover;
属性。当我使用 Chrome 时,它会产生非常奇怪的像素化效果。另一方面,FireFox 可以毫无问题地绘制图片。这是 chrome 的 bug 还是只是他们的渲染算法不太好?
左边是firefox的图像,右边是chrome的图像,检查手臂和身体。
chrome版本107.0.5304.107 火狐浏览器版本107.0
解决方法是行不通的,因为这只能解决我的问题。 这是另一台电脑上同样的问题。 (不同品牌,不同规格) 问题仍然存在。 (右边是Chrome,仍然检查手臂)
image-rendering
是不可预测的显然,大多数基于 chromium(blink 引擎)的浏览器(google chrome、opera、vivaldi、brave、ie13/edge 等)会根据所需的缩放/调整大小在不同的插值方法之间切换,以优化渲染性能。
左:内在 3000x3000px 缩小至 240x240px
看起来不错——大概是双线性或双三次插值。
右:内在 4000x3000px 缩小并适合 240x240px
明显的“锯齿状”边缘——大概是一个简单的最近邻插值——通过额外的平移/拟合引入
object-fit:cover
显然,当两者都满足时,基于 chromium 的浏览器将回退到更简单的最近邻下采样方法
差异显着。
但是,上述方法只会减轻这种影响。
希望我们会看到为
image-rendering
值(如 smooth
或 high-quality
)指定更好的支持/实现。
function replaceImg() {
let images = document.querySelectorAll("img");
images.forEach((img) => {
let wNative = img.naturalWidth;
let hNative = img.naturalHeight;
let wRendered = img.offsetWidth;
let hRendered = img.offsetHeight;
let scale =
Math.min(...[wRendered, hRendered]) / Math.min(...[wNative, hNative]);
if (scale < 0.3) {
scale *= 2;
(async() => {
let dataUrl = await imageToDataURL(
img.src,
wNative * scale,
hNative * scale
);
img.src = dataUrl;
img.classList.add("imgDataUrl");
})();
}
});
async function imageToDataURL(imageUrl, width, height) {
let img = await fetch(imageUrl);
img = await img.blob();
let bitmap = await createImageBitmap(img);
let canvas = document.querySelector("canvas") ? document.querySelector("canvas") : document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
ctx.drawImage(bitmap, 0, 0, width, height);
let dataUrl = canvas.toDataURL("image/jpeg");
return dataUrl;
}
}
* {
box-sizing: border-box
}
body {
font-family: sans-serif
}
figure {
width: 240px;
height: 240px;
display: inline-block;
}
img {
max-width: 100%;
height: 100%;
aspect-ratio: 1/1;
object-fit: cover;
}
.obj-contain {
object-fit: none;
object-fit: none;
}
.pixelated {
image-rendering: pixelated;
}
.crisp {
image-rendering: crisp-edges;
}
.auto {
image-rendering: auto;
}
.imgDataUrl {
outline: 2px solid red;
}
<p><button onclick="replaceImg()"> Replace with dataURL</button></p>
<figure>
3000 x 3000: auto
<img class="auto" src="https://picsum.photos/id/76/3000/3000" alt="">
</figure>
<figure>
4000 x 3000: auto
<img class="auto" src="https://picsum.photos/id/76/4000/3000" alt="">
</figure>
<figure>
1200 x 1000: auto
<img class="auto" src="https://picsum.photos/id/76/1000/800" alt="">
</figure>
<figure>
240 x 240: auto
<img class="auto" src="https://picsum.photos/id/76/240/240" alt="">
</figure>
<figure>
300 x 240: auto
<img class="auto" src="https://picsum.photos/id/76/300/240" alt="">
</figure>
<figure>
600 x 480: auto
<img class="auto" src="https://picsum.photos/id/76/600/480" alt="">
</figure>
<figure>
3000 x 1500: auto
<img class="auto" src="https://picsum.photos/id/76/3000/1500" alt="">
</figure>
<figure>
1600 x 800: auto
<img class="auto" src="https://picsum.photos/id/76/1600/800" alt="">
</figure>
<figure>
800 x 400: auto
<img class="auto" src="https://picsum.photos/id/76/800/400" alt="">
</figure>
<figure>
600 x 300: auto
<img class="auto" src="https://picsum.photos/id/76/600/300" alt="">
</figure>
<figure>
800 x 400: pixelated
<img class="pixelated" src="https://picsum.photos/id/76/600/300" alt="">
</figure>
即使困难,也有很多像素插值选项(快速双线性、双三次、lanczos、b 样条、AI/DL 训练算法等)。
公平地说:
正如@Rene van der Lende 评论的:
Chromiums 缩小图像渲染本身并不坏 - 有时 Firefox(或 safari 和非 Apple Webkit 浏览器,如 Epiphany 或 midori)可能会遇到类似的问题 但在其他情况下。
将此代码添加到您的图像 CSS 中:
变换:translate3d(0px, 0px, 0.1px);
除了像素消失之外,您不会看到差异:-)
你应该尝试一下:
溢出剪辑边距:未设置;
溢出:可见;
它对我有用。