Object-fit : обложка дает пиксельные изображения на хроме

У меня есть простой элемент карточки с тегом <img> внутри. Изображение имеет свойство object-fit: cover;. Когда я нахожусь в хроме, он имеет очень странный пиксельный эффект. С другой стороны, FireFox рисует картинку без проблем. Это ошибка хрома или просто их алгоритм рендеринга не очень хорош?

слева картинка фаерфокса, справа хрома, проверьте руки и корпус.

хром Версия 107.0.5304.107 фаерфокс версия 107.0

Обходной путь не сработает, так как это будет исправление только с моей стороны. Вот такая же проблема на другом компе. (другой бренд, разные характеристики) Проблема все еще сохраняется. (хром справа, все еще проверяйте руки)

Вы пробовали: stackoverflow.com/questions/71251416/…?

AtomicUs5000 19.11.2022 20:51

Вы можете попробовать image-rendering, но это также может быть ошибка на стороне GPU.

Akxe 12.01.2023 12:15

изменил вопрос, чтобы ответить на комментарии

Skin_phil 12.01.2023 12:57

Я также пробовал рендеринг изображений, свойства которого в основном устарели или не дают никакого результата.

Skin_phil 12.01.2023 13:04

@AtomicUs5000 Да, GPU работает, но это только на стороне клиента, так что на самом деле проблема не решается.

Ben Hollier 12.01.2023 16:03

Вам нужно опубликовать исходное изображение и код, который вы используете, потому что со случайными изображениями разных размеров и минимальным кодом проблема не может быть воспроизведена. Я использую Chrome/Edge и Firefox, все версии 109. x64. Мой тест: Codepen. Вертикальные и изогнутые кабели моста не показывают пикселизацию, на самом деле Chrome сглаживает чуть лучше, чем Firefox. Я позаботился о том, чтобы использовать изображения с высоким контрастом между светлыми и темными цветами.

Rene van der Lende 14.01.2023 17:26
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
8
6
406
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

TL;DR: вы можете только смягчить этот эффект — image-rendering непредсказуемо

Текущее состояние 2023-01-18

Судя по всему, большинство браузеров на основе хрома (blink engine) (google chrome, Opera, Vivaldi, Brave, ie13/edge и т. д.) переключаются между различными методами интерполяции в зависимости от требуемого масштабирования/изменения размера для оптимизации производительности рендеринга.

Слева: внутренний размер 3000 x 3000 пикс. уменьшен до 240 x 240 пикс. Выглядит нормально — предположительно, билинейная или бикубическая интерполяция.

Справа: внутренний размер 4000 x 3000 пикс. уменьшен и вписан в размер 240 x 240 пикс. Заметные «зубчатые» края — предположительно, простая интерполяция ближайшего соседа — введены дополнительным панорамированием/подгонкой через object-fit:cover

По-видимому, браузеры на основе хрома вернутся к более упрощенному методу понижения частоты дискретизации ближайшего соседа, когда оба

  • внутренние и визуализированные размеры, а также
  • внутреннее и визуализированное соотношение сторон

существенно различаются.

Обходной путь: избегайте чрезмерного изменения размера, оптимизируя изображения.

  • избегайте излишне высоких разрешений - попробуйте изменить размер и обрезать изображения, чтобы они соответствовали фактическим размерам макета: например. если ваше изображение всегда используется с соотношением сторон 1/1 - вам лучше обрезать изображение 16/9. На жаргоне Google Light House: «Показывайте изображения соответствующего размера, чтобы сохранить сотовые данные и сократить время загрузки».
  • определить кандидатов на отзывчивое изображение и/или изображение Art-Direction:
    Журнал Smashing: адаптивные изображения, сделанные правильно: руководство и исходный код

Однако вышеупомянутые подходы лишь смягчат этот эффект.

Надеюсь, мы увидим лучшую поддержку/реализацию, как указано для значений image-rendering, таких как smooth или high-quality.

Веб-документы MDN: рендеринг изображений

Фрагмент примера (только для сравнения/тестирования)

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>

Пример Codepen для тестирования

»Четкость в глазах смотрящего«

Несмотря на сложность, существует множество вариантов интерполяции пикселей (быстрая билинейная, бикубическая, Ланцоша, b-сплайн, алгоритмы, обученные AI/DL и т. д.).

Давайте будем честными:

  • некоторые пользователи предпочтут слегка «зубчатые» края слегка «размытым»
    (пустяки: было очень важно, когда четкий тип и другие шрифты были внедрены технологии сглаживания — я рад, что фронт сглаживания выиграл эту войну...)
  • последние будут жаловаться на размытость рендеринга.
    См. также SO вопросы, решающие противоположную проблему
  • другие, использующие дисплеи с высокой плотностью пикселей, могут вообще не заметить вышеупомянутые «ленивые» приемы оптимизации.

Как прокомментировал @Rene van der Lende:
Рендеринг изображений с уменьшенным масштабом Chromium сам по себе не является плохим — иногда Firefox (или браузеры Safari и не-Apple WebKit, такие как Epiphany или Midori) могут бороться с аналогичными проблемами, но в других случаях.

Я знал, что это как-то связано с выборкой пикселей вверх/вниз: ближайший сосед/сохранение деталей/сглаживание, как в Photoshop для изменения размера изображений. Что-то должно дать, не так ли? Отсюда моя просьба к ОП о размещении исходного изображения. Кстати, в некоторых случаях у Firefox тоже есть свои проблемы... Вы получили мой голос!😉

Rene van der Lende 15.01.2023 03:37

Спасибо! Боюсь, у нас никогда не будет более надежных вариантов рендеринга. Список параметров, похожий на Photoshop, действительно был бы намного более интуитивным (например, «нет», «ближайший сосед», «биллинейный», «бикубический» и т. д.) «-webkit-optimize-contrast» — мое любимое семантическое зверство.

herrstrietzel 15.01.2023 21:07

Другие вопросы по теме