Wyświetlacze o wysokiej gęstości pikseli szybko stają się normą. Twórcy treści muszą się do tego dostosować. Oto krótki przewodnik, jak udostępniać w internecie obrazy wysokiej jakości bez polyfillów, JavaScriptu, sztuczek w CSS i funkcji przeglądarki, które nie zostały jeszcze wdrożone. Jednym słowem: bez drastycznej zmiany procesu.
Obecnie istnieje wiele propozycji obrazów responsywnych, z których wiele wymaga znacznych zmian w programie internetowym. Atrybut srcset
<img>
zgodny ze standardami jest trudny do wdrożenia, zwłaszcza ze względu na złożoność dodatkowego wyboru srcset
na podstawie widoku:
banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x
Mimo że właściwość CSS image-set
używa tylko atrybutu devicePixelRatio
do określenia, który obraz ma być wczytany, zmusza ona deweloperów do napisania dodatkowej znaczniki dla każdego obrazu.
Inne propozycje, takie jak element <picture>
, są jeszcze bardziej szczegółowe.
Ponadto nie są one zgodne ze standardami, więc ich powszechna dostępność jest jeszcze bardziej ograniczona niż w przypadku atrybutu srcset. Jedynymi innymi alternatywami są rozwiązania po stronie JavaScript i serwera, ale mają one swoje wady, o których piszemy w innych artykułach.
W tym artykule omówimy kilka zastosowań obrazów, które są często używane w internecie, i zaproponujemy proste rozwiązania, które działają zarówno na ekranach o wysokiej gęstości pikseli, jak i zwykłych. W ramach tej dyskusji każde urządzenie, które podaje wartość window.devicePixelRatio
większą niż 1, może być uznawane za urządzenie o wysokiej rozdzielczości, ponieważ oznacza to, że piksele CSS nie są takie same jak piksele urządzenia i że obrazy są powiększane.
Podsumowanie:
- W miarę możliwości używaj CSS/SVG zamiast obrazów rastrowych.
- Domyślnie używaj obrazów zoptymalizowanych pod kątem wyświetlaczy o wysokiej gęstości pikseli.
- Używaj plików PNG do prostych rysunków i grafiki pikseli (np. logo).
- W przypadku obrazów o wielu kolorach (np. zdjęć) używaj skompresowanych plików JPEG.
- Zawsze ustawiaj dokładne rozmiary (za pomocą CSS lub HTML) dla wszystkich elementów obrazu.
proste rysunki i pixel art;
Małych obrazów można często uniknąć, korzystając z funkcji CSS lub formatu SVG.
Nie musisz używać obrazów do zaokrąglonych narożników, ponieważ właściwość CSS border-radius
jest powszechnie obsługiwana. Podobnie, czcionki niestandardowe są powszechnie obsługiwane, więc nie zalecamy używania tekstu „obrazkowego”.
W niektórych przypadkach, np. w przypadku logo, obraz może być jedynym sposobem na przekazanie informacji. Na przykład logo Chrome ma rozmiar 256 x 256. Na wyświetlaczu Retina widać aliasing linii na ukos i w zakrzywieniach, który wygląda niezbyt dobrze, zwłaszcza w porównaniu z ostrą krawędzią renderowanego tekstu:


Wymiary naturalne: 256x256px
, rozmiar komponentu: 31 kB
, format: PNG
Przekonało Cię to? Cieszę się. Teraz użyjemy obrazu o wysokiej gęstości. Możesz chcieć zaoszczędzić miejsce, przechowując logo w formacie JPEG, ale nie jest to dobry pomysł, ponieważ zapisywanie logo i innych grafik w formacie stratnym może powodować artefakty. W tym przypadku problem został wyolbrzymiony przez bardzo wysokie skompresowanie, ale zwróć uwagę na pasy na gradientach, plamki na białym tle i niechlujne linie:


Wymiary naturalne: 512x512px
, rozmiar komponentu: 13 kB
, format: JPEG
W przypadku stosunkowo małych obrazów należy użyć PNG 2x. Pamiętaj, że różnica w rozmiarze między obrazem PNG w rozmiarze 1x a 2x jest na ogół dość duża (w tym przypadku 52 kB). W przypadku logo jest to jednak twarz Twojej witryny i pierwsza rzecz, którą zobaczą użytkownicy. Jeśli z założenia zrezygnujesz z jakości na rzecz rozmiaru, Twoi użytkownicy zobaczą też ostatnią rzecz.
Oto logo Chrome w całej okazałości, zmniejszone do połowy naturalnych wymiarów, aby pasowało do wyświetlaczy 2x:


Wymiary naturalne: 512x512px
, rozmiar komponentu: 83 kB
, format: PNG
Oto znaczniki potrzebne do renderowania tego widoku:
<img src="chrome2x.png" style="width: 256px; height: 256px;"/>
Zwróć uwagę, że na obrazie podałem szerokość i wysokość. Jest to konieczne, ponieważ naturalny rozmiar obrazu to 512 pikseli. Jest to też korzystne dla wydajności, ponieważ silnik renderowania ma dobrą znajomość rozmiaru elementu i nie musi zbytnio się wysilać, aby go obliczyć.
Jednym z możliwych sposobów optymalizacji jest zmniejszenie 24-bitowego pliku PNG do 8-bitowego z paletą. Ta metoda sprawdza się w przypadku obrazów o małej liczbie kolorów, w tym logo Chrome. Aby przeprowadzić optymalizację, możesz użyć narzędzia takiego jak http://pngquant.org/. Widać tu nieco pasmowania, ale plik ma tylko 13 KB, co oznacza aż 6-krotne zmniejszenie rozmiaru w porównaniu z oryginalnym plikiem PNG o wymiarach 512 x 512.


Wymiary naturalne: 512x512px
, rozmiar komponentu: 13 kB
, format: PNG,
8-bit palette
Obrazy w różnych kolorach
Napisałem artykuł na stronie HTML5Rocks omawiający różne techniki tworzenia obrazów w wersji mobilnej oraz przeprowadziłem badania dotyczące kompresji JPEG 1x i 2x i porównałem uzyskane rozmiary i jakość obrazu. Oto jeden taki kafelek z powyższego artykułu:

Obrazy zostały opisane pod kątem stopnia kompresji (wskazanego przez jakość JPEG), rozmiaru (w bajtach) oraz mojej subiektywnej opinii na temat ich względnej wierności wizualnej (oznaczone numerami). Ciekawostką jest to, że bardzo skompresowany obraz 2x (oznaczony numerem 3) jest mniejszy i lepiej wygląda niż nieskompresowany obraz 1x (oznaczony numerem 4). Innymi słowy, między obrazem 4 a 3 udało nam się poprawić jakość obrazu przez podwojenie każdego wymiaru i znaczne zwiększenie kompresji, a jednocześnie zmniejszenie rozmiaru o 2 kB.
Kompresja, wymiary i jakość obrazu
Chcę uzyskać więcej informacji na temat kompromisów między poziomem kompresji, wymiarami obrazu, jakością obrazu i jego rozmiarem. Na podstawie powyższego badania przeprowadziłem badanie z taką hipotezą:
Hipoteza
Przy wystarczającym stopniu kompresji obraz w rozmiarach 2 x będzie wyglądał tak samo jak obraz w rozmiarach 1 x przy innej (niższej) kompresji. W tym przypadku jednak skompresowany obraz 2 x będzie mniejszy niż obraz 1 x.
Przetwarzanie
- Na podstawie obrazu 2x wygeneruj obraz 1x.
- Skompresuj oba obrazy na różnych poziomach.
- Utwórz stronę testową, na której oba zestawy obrazów będą widoczne obok siebie.
- Znajdź w obu zestawach miejsce, w którym obrazy są identyczne.
- Zwróć uwagę na równoważne rozmiary i poziomy kompresji obrazów.
- Wypróbuj je na wyświetlaczu 1x i 2x.
Stworzyłem aplikację do porównywania obrazów obok siebie, podobną do widoku porównawczego Lightrooma. Chodzi o to, aby obok siebie wyświetlić obrazy w powiększeniu 1x i 2x, ale też umożliwić powiększenie dowolnej sekcji obrazu, aby uzyskać więcej szczegółów. Możesz też wybrać format JPEG lub WebP i zmienić jakość kompresji, aby porównać rozmiar pliku i jakość obrazu. Chodzi o to, aby dostosować ustawienia kilku obrazów, określić, jakie kompromisy w zakresie jakości kompresji, skalowania i formatu są dla Ciebie odpowiednie, a następnie zastosować te ustawienia do wszystkich obrazów.

Narzędzie możesz wypróbować. Możesz powiększyć obraz, wybierając obszar, który chcesz powiększyć.
Analiza
Na wstępie powiem, że jakość obrazu jest sprawą subiektywną. Poza tym konkretny przypadek użycia prawdopodobnie określi, jakie są Twoje priorytety w zakresie wierności obrazu i rozmiaru pliku. Dodatkowo różne rodzaje funkcji obrazu reagują inaczej na jakość skalowania i kompresji, więc uniwersalne rozwiązanie niekoniecznie może się tu sprawdzić. Celem tego narzędzia jest pomoc w rozwinięciu intuicji dotyczącej jakości obrazu, kompresji, skali i formatów.
Po zabawie z powiększeniem obrazu szybko zauważyłem kilka rzeczy. Po pierwsze, wolę obrazy quality=30 dpr=2x
niż quality=90
dpr=1x
, ponieważ są one bardziej szczegółowe. Te obrazy są porównywalne również pod względem rozmiaru pliku (w przypadku samolotu skompresowany obraz 2x zajmuje 76 kB, a nieskompresowany obraz 1x – 80 kB).
Wyjątkiem od tej reguły są obrazy z gradientami, które są bardzo skompresowane (quality<30
). Zdjęcia te często mają pasy kolorów, które są równie niekorzystne niezależnie od skali obrazu. Przykładem są próbki ptaków i samochodów dostępne w narzędziu.
Obrazy WebP wyglądają o wiele lepiej niż JPEG, zwłaszcza przy niskiej kompresji. Pasy kolorów są znacznie mniej widoczne. I na koniec: obrazy WebP są znacznie bardziej zwarte.
Zastrzeżenia i podsumowanie
Uzyskanie dobrego wyglądu obrazów na ekranach o dużej gęstości pikseli to tylko połowa problemów związanych z obrazami spowodowanych ogromnymi różnicami w wyświetlaczach. W niektórych przypadkach możesz chcieć wyświetlać zupełnie inne obrazy w zależności od rozmiaru widocznego obszaru. Na przykład zdjęcie profilowe Obamy może być odpowiednie na ekran telefonu, ale stojak przed nim i flaga za nim mogą lepiej pasować do ekranu laptopa.
Celowo pomijam temat „kierowanie artystyczne”, aby skupić się tylko na obrazach o wysokiej rozdzielczości. Ten problem można rozwiązać na kilka różnych sposobów: za pomocą definicji media, obrazów tła, kodu JavaScript, nowych funkcji, takich jak image-set
, lub na serwerze. Ten temat jest omówiony w artykule Obrazy o wysokiej rozdzielczości w przypadku zmiennej gęstości pikseli.
Na koniec kilka otwartych kwestii:
- Wpływ wysokiej kompresji na wydajność. Jakie są konsekwencje dekodowania bardzo skompresowanych obrazów?
- Jakie są konsekwencje konieczności zmniejszenia rozmiaru obrazu, gdy wczytujemy obraz 2x na wyświetlaczu 1x?
Podsumowując, zamiast obrazów rastrowych używaj CSS i SVG. Jeśli obrazy rastrowe są wymagane, użyj formatu PNG w przypadku obrazów z ograniczoną paletą i wieloma jednolitymi kolorami oraz formatu JPEG w przypadku obrazów z wieloma kolorami i gradientami. Wspaniałą rzeczą w tym podejściu jest to, że znaczniki są praktycznie niezmienione. Od programisty stron internetowych wymagamy tylko, aby wygenerował zasoby w rozmiarze 2x i odpowiednio dopasował rozmiar obrazów w DOM.
Aby dowiedzieć się więcej, przeczytaj artykuł Scotta Jehla na podobny temat. Życzymy Ci ostrych obrazów i niskiego zużycia danych komórkowych.