Hình ảnh có DPI cao và dễ dùng

Màn hình có mật độ điểm ảnh cao đang nhanh chóng trở thành tiêu chuẩn. Nhà sáng tạo nội dung cần thích ứng với thực tế này. Đây là hướng dẫn ngắn về cách phân phát hình ảnh chất lượng cao trên web hiện nay mà không cần polyfill, JavaScript, các bản hack CSS và các tính năng trình duyệt chưa được triển khai đầy đủ. Tóm lại: không có thay đổi lớn nào đối với quy trình làm việc của bạn.

Hiện có nhiều đề xuất về hình ảnh thích ứng, trong đó có nhiều đề xuất liên quan đến những thay đổi đáng kể đối với nhà phát triển web. Thuộc tính srcset <img> theo dõi tiêu chuẩn rất khó triển khai, đặc biệt là với độ phức tạp của lựa chọn bổ sung dựa trên khung nhìn của srcset:

banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x

Mặc dù thuộc tính CSS image-set chỉ sử dụng devicePixelRatio để quyết định hình ảnh nào sẽ tải, nhưng thuộc tính này vẫn buộc nhà phát triển phải viết nhiều mã đánh dấu bổ sung cho mỗi hình ảnh.

Các đề xuất khác, chẳng hạn như phần tử <picture>, thậm chí còn dài dòng hơn. Hơn nữa, chúng không theo dõi tiêu chuẩn, vì vậy, khả năng sử dụng phổ biến của chúng còn vượt xa thuộc tính srcset. JavaScript và các giải pháp phía máy chủ là giải pháp thay thế duy nhất, nhưng các phương pháp này cũng có những hạn chế riêng như đã đề cập trong các bài viết khác.

Bài viết này sẽ trình bày một số cách sử dụng hình ảnh thường thấy trên web và đề xuất các giải pháp đơn giản hoạt động trên màn hình có mật độ pixel cao cũng như màn hình thông thường. Đối với mục đích của cuộc thảo luận này, mọi thiết bị báo cáo window.devicePixelRatio lớn hơn 1 đều có thể được coi là DPI cao, vì điều đó có nghĩa là pixel CSS không giống với pixel thiết bị và hình ảnh đang được tăng tỷ lệ.

Sau đây là bản tóm tắt:

  • Sử dụng CSS/SVG thay vì hình ảnh đường quét nếu có thể.
  • Sử dụng hình ảnh được tối ưu hoá cho màn hình có mật độ điểm ảnh cao theo mặc định.
  • Sử dụng tệp PNG cho bản vẽ đơn giản và hình ảnh pixel (ví dụ: biểu trưng).
  • Sử dụng tệp JPEG nén cho hình ảnh có nhiều màu (ví dụ: ảnh).
  • Luôn đặt kích thước rõ ràng (bằng CSS hoặc HTML) trên tất cả các phần tử hình ảnh.

Bản vẽ đơn giản và nghệ thuật điểm ảnh

Bạn thường có thể tránh hoàn toàn hình ảnh nhỏ bằng cách sử dụng các tính năng CSS hoặc SVG. Ví dụ: bạn không cần sử dụng hình ảnh cho các góc bo tròn vì thuộc tính CSS border-radius được hỗ trợ rộng rãi. Tương tự, phông chữ tùy chỉnh được hỗ trợ rộng rãi, vì vậy, bạn không nên sử dụng văn bản "hình ảnh".

Tuy nhiên, trong một số trường hợp, chẳng hạn như biểu trưng, hình ảnh có thể là cách duy nhất để tiếp tục. Ví dụ: biểu trưng Chrome này có kích thước tự nhiên là 256x256. Trên màn hình Retina, bạn có thể thấy răng cưa đường kẻ ở đường chéo và đường cong, trông rất thô và xấu, đặc biệt là khi so sánh với văn bản được kết xuất sắc nét:

Chrome 1x
Png 1x

Kích thước tự nhiên: 256x256px, kích thước thành phần: 31 kB, định dạng: PNG

Bạn đã tin tưởng chưa? Tốt. Bây giờ, hãy sử dụng hình ảnh có mật độ điểm ảnh cao. Bạn có thể muốn tiết kiệm dung lượng bằng cách lưu biểu trưng dưới dạng JPEG, nhưng đây có thể không phải là ý tưởng hay vì việc lưu biểu trưng và các đồ hoạ khác ở định dạng có tổn hao thường sẽ tạo ra các cấu phần phần mềm. Trong trường hợp này, tôi đã phóng đại vấn đề bằng cách sử dụng mức độ nén rất cao, nhưng hãy lưu ý các dải trên hiệu ứng chuyển màu, các đốm trên nền trắng và các đường kẻ lộn xộn:

Chrome 2x
Jpeg 2x

Kích thước tự nhiên: 512x512px, kích thước thành phần: 13 kB, định dạng: JPEG

Đối với hình ảnh tương đối nhỏ, bạn nên sử dụng tệp PNG 2x. Xin lưu ý rằng sự khác biệt về kích thước giữa tệp PNG 1x và 2x thường khá lớn (52 kB trong trường hợp này). Tuy nhiên, trong trường hợp của biểu trưng, đó là bộ mặt của trang web và là điều đầu tiên mà khách truy cập sẽ thấy. Nếu bạn quá chú trọng đến kích thước mà bỏ qua chất lượng, thì đó cũng sẽ là điều cuối cùng mà khách truy cập nhìn thấy!

Dưới đây là biểu trưng Chrome ở mọi góc độ, được giảm kích thước xuống một nửa kích thước tự nhiên cho màn hình 2x:

Chrome 2x
Png 2x

Kích thước tự nhiên: 512x512px, kích thước thành phần: 83 kB, định dạng: PNG

Mã đánh dấu để tạo bản kết xuất ở trên như sau:

<img src="chrome2x.png" style="width: 256px; height: 256px;"/>

Xin lưu ý rằng tôi đã chỉ định chiều rộng và chiều cao trên hình ảnh. Điều này là cần thiết vì kích thước tự nhiên của hình ảnh là 512 px. Điều này cũng tốt cho hiệu suất vì công cụ kết xuất nắm bắt tốt kích thước của phần tử và không cần phải nỗ lực quá nhiều để tính toán kích thước đó.

Một cách tối ưu hoá có thể hiệu quả là giảm tệp PNG 24 bit xuống tệp PNG 8 bit có bảng màu. Cách này phù hợp với những hình ảnh có ít màu, bao gồm cả biểu trưng Chrome. Để thực hiện việc tối ưu hoá này, bạn có thể sử dụng một công cụ như http://pngquant.org/. Bạn có thể thấy một chút dải màu ở đây, nhưng tệp này chỉ có 13 kB, tức là tiết kiệm được kích thước gấp 6 lần so với tệp PNG 512x512 ban đầu.

Chrome 2x 8bit
Png 2x 8bit

Kích thước tự nhiên: 512x512px, kích thước thành phần: 13 kB, định dạng: PNG, 8-bit palette

Hình ảnh có nhiều màu sắc

Tôi đã viết một bài viết trên HTML5Rocks khảo sát một số kỹ thuật hình ảnh thích ứng và thực hiện một số nghiên cứu về việc nén JPEG 1x và 2x, đồng thời so sánh kích thước và chất lượng hình ảnh thu được. Sau đây là một thẻ thông tin như vậy trong bài viết trên:

Thẻ thông tin.

Tôi đã gắn nhãn cho các hình ảnh theo mức độ nén (được biểu thị bằng chất lượng JPEG), kích thước (tính bằng byte) và ý kiến chủ quan của tôi về độ trung thực hình ảnh tương đối (được xếp hạng theo số). Điều thú vị ở đây là hình ảnh 2x được nén nhiều (được gắn nhãn 3) có kích thước nhỏ hơntrông đẹp hơn so với hình ảnh 1x không nén (được gắn nhãn 4). Nói cách khác, giữa hình ảnh 4 và 3, chúng ta đã cải thiện chất lượng hình ảnh bằng cách tăng gấp đôi mỗi kích thước và tăng đáng kể mức độ nén, đồng thời giảm kích thước xuống 2 kB.

Nén, kích thước và chất lượng hình ảnh

Tôi muốn hiểu rõ hơn một chút về sự đánh đổi giữa mức độ nén, kích thước hình ảnh, chất lượng hình ảnh và kích thước hình ảnh. Tôi đã chạy một nghiên cứu với giả thuyết sau đây dựa trên nghiên cứu ở trên:

Giả thuyết

Với mức độ nén đủ, hình ảnh 2x sẽ trông tương đương với cùng một hình ảnh ở kích thước 1x ở một số mức nén khác (thấp hơn). Tuy nhiên, trong trường hợp này, hình ảnh 2x được nén nhiều sẽ có kích thước nhỏ hơn hình ảnh 1x.

Quy trình

  • Với hình ảnh 2x, hãy tạo hình ảnh 1x.
  • Nén cả hai hình ảnh ở nhiều cấp độ.
  • Tạo một trang thử nghiệm hiển thị cả hai nhóm hình ảnh cạnh nhau.
  • Tìm vị trí trong hai tập hợp mà hình ảnh tương đương nhau.
  • Lưu ý các kích thước hình ảnh và mức độ nén tương đương.
  • Thử trên cả màn hình 1x và 2x.

Tôi đã xây dựng một ứng dụng so sánh hình ảnh cạnh nhau tương tự như chế độ xem so sánh của Lightroom. Mục đích là hiển thị hình ảnh 1x và 2x cạnh nhau, nhưng cũng cho phép bạn phóng to bất kỳ phần nào của hình ảnh để xem thêm chi tiết. Bạn cũng có thể chọn giữa định dạng JPEG và WebP và thay đổi chất lượng nén để xem kích thước tệp và chất lượng hình ảnh so sánh. Ý tưởng là điều chỉnh chế độ cài đặt cho một số hình ảnh, tìm ra chất lượng nén, tỷ lệ và định dạng so với chất lượng hình ảnh mà bạn cảm thấy thoải mái và sử dụng chế độ cài đặt đó cho tất cả hình ảnh.

Ảnh chụp màn hình so sánh

Bạn có thể sử dụng công cụ này. Bạn có thể phóng to hình ảnh bằng cách chọn một khu vực phụ để phóng to.

Phân tích

Trước tiên, tôi xin nói rằng chất lượng hình ảnh là một khái niệm chủ quan. Ngoài ra, trường hợp sử dụng cụ thể của bạn có thể xác định mức độ ưu tiên của bạn trong phổ độ trung thực hình ảnh so với kích thước tệp. Ngoài ra, các loại tính năng hình ảnh khác nhau phản ứng khác nhau với chất lượng tỷ lệ và nén, vì vậy, giải pháp phù hợp với mọi trường hợp có thể không hoạt động ở đây. Mục đích của công cụ này là giúp bạn hình dung được các mức nén, tỷ lệ và định dạng chất lượng hình ảnh.

Khi chơi với công cụ thu phóng hình ảnh, tôi nhanh chóng nhận thấy một vài điều. Trước tiên, tôi thích hình ảnh quality=30 dpr=2x hơn hình ảnh quality=90 dpr=1x vì hình ảnh quality=30 dpr=2x có nhiều chi tiết hơn. Các hình ảnh này cũng có kích thước tệp tương đương nhau (trong trường hợp máy bay, hình ảnh nén 2x có kích thước 76 kB trong khi hình ảnh 1x không nén có kích thước 80 kB).

Các trường hợp ngoại lệ của quy tắc này là hình ảnh được nén nhiều (quality<30) có hiệu ứng chuyển màu. Những hình ảnh này thường bị hiện tượng dải màu, điều này cũng gây ảnh hưởng xấu bất kể tỷ lệ hình ảnh. Mẫu chim và ô tô có trong công cụ này là ví dụ về điều này.

Hình ảnh WebP trông rõ ràng hơn nhiều so với JPEG, đặc biệt là ở mức độ nén thấp. Hiện tượng dải màu này có vẻ ít nghiêm trọng hơn nhiều. Cuối cùng, hình ảnh WebP nhỏ gọn hơn nhiều.

Những điểm cần lưu ý và kết luận

Việc làm cho hình ảnh trông đẹp trên màn hình có mật độ điểm ảnh cao chỉ là một nửa trong số các vấn đề liên quan đến hình ảnh do sự khác biệt lớn về màn hình. Trong một số trường hợp, bạn nên phân phát hình ảnh hoàn toàn khác nhau tuỳ thuộc vào kích thước khung nhìn. Ví dụ: ảnh chân dung của Obama có thể phù hợp với màn hình cỡ điện thoại, nhưng giá đỡ trước mặt và lá cờ phía sau ông, cũng như một số hình ảnh khác có thể phù hợp hơn với màn hình máy tính xách tay.

Tôi cố tình tránh chủ đề "hướng dẫn nghệ thuật" này để chỉ tập trung vào hình ảnh có DPI cao. Bạn có thể giải quyết vấn đề này bằng một số phương pháp khác nhau: sử dụng truy vấn nội dung đa phương tiện và hình nền, thông qua JavaScript, thông qua một số tính năng mới như image-set hoặc trên máy chủ. Chủ đề này được đề cập trong phần Hình ảnh có DPI cao cho mật độ pixel biến đổi.

Tôi xin kết thúc bằng một vài vấn đề còn tồn đọng:

  • Ảnh hưởng của mức độ nén cao đến hiệu suất. Hình phạt khi giải mã hình ảnh được nén ở mức độ cao là gì?
  • Việc phải giảm kích thước hình ảnh khi tải hình ảnh 2x trên màn hình 1x sẽ gây ra những hình phạt hiệu suất nào?

Tóm lại, hãy chọn CSS và SVG thay vì sử dụng hình ảnh đường quét. Nếu bạn bắt buộc phải sử dụng hình ảnh đường quét, hãy dùng PNG cho hình ảnh có bảng màu hạn chế và nhiều màu đồng nhất, đồng thời sử dụng JPEG cho hình ảnh có nhiều màu và độ dốc. Điều tuyệt vời về phương pháp này là phần đánh dấu của bạn hầu như không thay đổi. Tất cả những gì nhà phát triển web cần làm là tạo thành phần 2x và định cỡ hình ảnh của bạn đúng cách trong DOM.

Để đọc thêm, hãy xem bài viết của Scott Jehl về một chủ đề tương tự. Chúc hình ảnh của bạn luôn sắc nét và mức sử dụng dữ liệu di động của bạn luôn thấp!