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

Màn hình có mật độ pixel cao đang nhanh chóng trở thành thông thường. Các nhà sáng tạo nội dung cần phải 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 hiện nay trên web mà không có đoạn mã polyfill, JavaScript, tấn công CSS và các tính năng của trình duyệt chưa được triển khai. Tóm lại: không có thay đổi lớn nào đối với quy trình làm việc.

Hiện nay, có rất nhiều đề xuất hình ảnh thích ứng, nhiều đề xuất trong số đó liên quan đến những thay đổi đáng kể đối với nhà phát triển web. Rất khó triển khai thuộc tính srcset <img> theo dõi tiêu chuẩn, đặc biệt với sự phức tạp của việc 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 cần tải, nhưng 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, như phần tử <picture> thậm chí còn chi tiết hơn. Hơn nữa, chúng không được theo dõi tiêu chuẩn, vì vậy, khả năng sử dụng rộng rãi của chúng thậm chí còn xa hơn so với thuộc tính srcset. JavaScript và giải pháp phía máy chủ là giải pháp thay thế duy nhất, nhưng những phương pháp này có 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. Vì mục đích của cuộc thảo luận này, bất kỳ thiết bị nào 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 của 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 các màn hình có mật độ hiển thị cao theo mặc định.
  • Sử dụng PNG cho các bản vẽ và nghệ thuật điểm ảnh đơn giản (ví dụ: biểu trưng).
  • Sử dụng tệp JPEG nén cho hình ảnh có nhiều màu sắc (ví dụ: ảnh).
  • Luôn đặt kích thước rõ ràng (sử dụng CSS hoặc HTML) trên tất cả các phần tử hình ảnh.

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

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. Không cần sử dụng hình ảnh cho các góc tròn, chẳng hạn vì thuộc tính CSS border-radius được hỗ trợ rộng rãi. Tương tự, phông chữ tuỳ chỉnh cũng được hỗ trợ rộng rãi, vì vậy, bạn không nên sử dụng văn bản "có 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 để chuyển tiếp. 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 đường bị răng cưa ở các đường chéo và đường cong, trông không ổn và không đẹp, đặc biệt là khi so sánh với văn bản kết xuất sắc nét:

Chrome 1x
1x

Phương diện tự nhiên: 256x256px, kích thước nội dung: 31 kB, định dạng: PNG

Có thuyết phục không? Tốt quá. Bây giờ, hãy sử dụng hình ảnh có mật độ cao. Bạn có thể muốn tiết kiệm dung lượng bằng cách lưu trữ biểu trưng dưới dạng JPEG, nhưng đây không phải là ý tưởng hay vì việc lưu biểu trưng và đồ hoạ khác ở định dạng có tổn hao có xu hướng dẫn đến 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 dùng độ nén rất cao, nhưng hãy chú ý đến dải chuyển màu, các vệt lõm trên nền trắng và các đường rối mắt:

Chrome 2x
Jpeg 2x

Phương diện tự nhiên: 512x512px, kích thước nội dung: 13 kB, định dạng: JPEG

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

Dưới đây là biểu trưng Chrome toàn diện, được thu nhỏ bằng một nửa kích thước tự nhiên dành cho các màn hình 2x:

Chrome 2x
2x

Phương diện tự nhiên: 512x512px, kích thước nội dung: 83 kB, định dạng: PNG

Mã đánh dấu để hiển thị 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à 512px. Điều này cũng tốt cho hiệu suất vì công cụ kết xuất nắm được kích thước của các phần tử và không cần phải mất quá nhiều công sức để tính toán.

Một cách tối ưu hoá có thể hiệu quả là giảm PNG 24 bit thành tệp 8 bit theo bảng màu. Cách này phù hợp với hình ảnh có ít màu, bao gồm cả biểu trưng Chrome. Để tối ưu hoá việc 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 ở đây, nhưng tệp này chỉ có kích thước 13 kB, giúp tiết kiệm kích thước gấp 6 lần so với tệp PNG gốc 512x512.

Chrome 2x 8bit
Png 2x 8bit

Phương diện tự nhiên: 512x512px, kích thước nội dung: 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 HTML5Rocks khảo sát một số kỹ thuật hình ảnh thích ứng khác nhau và đã thực hiện một số nghiên cứu về việc nén ảnh JPEG 1x và 2x, đồng thời so sánh kích thước thu được và chất lượng hình ảnh. Dưới đây là một thẻ thông tin trong bài viết trên:

Thẻ thông tin.

Tôi đã gắn nhãn hình ảnh dựa trên 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 khi so sánh về hình ảnh (xếp hạng theo số). Điều thú vị ở đây là hình ảnh 2x được nén ở mức cao (đượ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 tôi đã tìm cách cải thiện chất lượng hình ảnh bằng cách tăng gấp đôi từng kích thước và tăng đáng kể độ nén, đồng thời giảm được kích thước 2 kB.

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

Tôi muốn biết thêm thông tin chi tiế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 đã tiến hành nghiên cứu với giả thuyết sau dựa trên nghiên cứu ở trên:

Giả thuyết

Khi 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ố lần 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 một 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 bộ hình ảnh đặt cạnh nhau.
  • Tìm vị trí tương đương trong hai nhóm ảnh.
  • Lưu ý rằng kích thước hình ảnh và mức nén tương đương.
  • Hãy thử trên cả màn hình 1x và 2x.

Tôi đã tạo 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 để có thêm chi tiết. Bạn cũng có thể chọn giữa định dạng JPEG và WebP, đồng thời thay đổi chất lượng nén để xem kích thước tệp và so sánh chất lượng hình ảnh. Bạn nên điều chỉnh chế độ cài đặt trên nhiều hình ảnh, tìm ra sự đánh đổi giữa chất lượng nén, tỷ lệ và định dạng và chất lượng hình ảnh mà bạn cảm thấy phù hợp, đồng thời sử dụng chế độ cài đặt đó cho tất cả hình ảnh.

Ảnh chụp màn hình thông tin 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 vùng phụ để phóng to.

Phân tích

Tôi xin nói rõ rằng chất lượng ảnh là một yếu tố mang tính chủ quan. Ngoài ra, trường hợp sử dụng cụ thể của bạn có thể sẽ cho biết các mối ưu tiên của bạn nằm ở đâu trong độ chân thực hình ảnh so với phổ 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 theo cách khác nhau đối với việc điều chỉnh tỷ lệ và chất lượng nén, vì vậy, một giải pháp chung cho mọi trường hợp có thể không nhất thiết phải hiệu quả ở đây. Mục đích của công cụ này là giúp bạn xây dựng trực quan về việc nén, điều chỉnh tỷ lệ và định dạng hình ảnh.

Từ việc sử dụng trình thu phóng hình ảnh, một vài điều nhanh chóng trở nên rõ ràng đối với tôi. Trước tiên, tôi thích hình ảnh quality=30 dpr=2x hơn hình ảnh quality=90 dpr=1x để tăng độ chi tiết. Các hình ảnh này cũng tương đương về kích thước tệp (trong trường hợp phẳng, hình ảnh 2x được nén là 76 kB trong khi hình ảnh 1x không nén là 80 kB).

Ngoại lệ của quy tắc này là hình ảnh được nén ở mức cao (quality<30) với độ dốc. Những đường liên kết này có xu hướng bị dải màu, và điều này cũng tệ không kém bất kể tỷ lệ hình ảnh. Các mẫu chim và ô tô có trong công cụ là ví dụ cho trường hợp này.

Hình ảnh WebP trông gọn gàng hơn JPEG, đặc biệt là ở mức nén thấp. Có vẻ như vấn đề về dải màu này không phải là vấn đề đáng kể. Cuối cùng, hình ảnh WebP nhỏ gọn hơn nhiều.

Cảnh báo và vây

Việc làm cho hình ảnh trông đẹp mắt 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ự thay đổi lớn về kích thước màn hình gây ra. Trong một số trường hợp, bạn có thể muốn phân phát các 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 ông Obama có thể phù hợp với màn hình cỡ điện thoại, nhưng ảnh đứng phía trước và cờ phía sau ông, một số ảnh có thể phù hợp hơn với màn hình máy tính xách tay.

Tôi cố ý tránh chủ đề "hướng nghệ thuật" này để chỉ tập trung vào những hình ảnh có DPI cao. Vấn đề này có thể được giải quyết bằng một số phương pháp: sử dụng truy vấn nội dung nghe nhì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 Hình ảnh DPI cao cho mật độ pixel thay đổi.

Tôi sẽ ký kết bằng một số vấn đề chưa giải quyết:

  • Ảnh hưởng của việc nén cao đến hiệu suất. Có những hình phạt nào khi giải mã hình ảnh được nén nhiều?
  • Các hình phạt về hiệu suất khi 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 là gì?

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ắ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 giới hạn và nhiều màu đồng nhất, đồng thời sử dụng tệp JPEG cho hình ảnh có nhiều màu sắc và độ dốc. Điều tuyệt vời của phương pháp này là mã đá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 yêu cầu là tạo thành phần gấp đôi và định kích thước hình ảnh đú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ự. Có thể hình ảnh của bạn trông sắc nét và mức sử dụng dữ liệu di động thấp!