Hầu hết lưu lượng truy cập tải xuống đều bao gồm hình ảnh. Do đó, hình ảnh có thể tải xuống càng nhỏ thì trải nghiệm mạng mà ứng dụng của bạn có thể mang lại cho người dùng càng tốt. Trang này cung cấp hướng dẫn về cách làm cho tệp hình ảnh nhỏ hơn và thân thiện hơn với mạng.
Giới thiệu về các định dạng hình ảnh
Ứng dụng Android thường sử dụng hình ảnh có một hoặc nhiều định dạng tệp sau: AVIF, PNG, JPG và WebP. Đối với mỗi định dạng này, có các bước bạn có thể thực hiện để giảm kích thước hình ảnh.
AVIF
Android 12 (API cấp độ 31) trở lên hỗ trợ hình ảnh sử dụng Định dạng tệp hình ảnh AV1 (AVIF). AVIF là một định dạng vùng chứa dành cho hình ảnh và trình tự của hình ảnh được mã hóa bằng AV1. AVIF tận dụng lợi thế của nội dung được mã hóa trong khung hình từ việc nén video. Điều này giúp cải thiện đáng kể chất lượng hình ảnh cho cùng một kích thước tệp khi so với các định dạng hình ảnh cũ, chẳng hạn như JPEG. Để hiểu sâu hơn về ưu điểm của định dạng này, vui lòng xem bài đăng trên blog của Jump Archibald.
PNG
Cốt lõi của việc làm cho tệp PNG nhỏ hơn là giảm số lượng màu sắc duy nhất được sử dụng trong mỗi hàng pixel bao gồm hình ảnh. Bằng cách sử dụng ít màu sắc hơn, bạn có thể cải thiện tiềm năng nén ở tất cả các giai đoạn khác của quy trình.
Việc giảm số lượng màu duy nhất tạo nên sự khác biệt đáng kể vì hiệu quả nén PNG là một phần hàm của mức độ thay đổi các màu pixel liền kề theo chiều ngang. Do đó, việc giảm số lượng màu duy nhất trong mỗi hàng của hình ảnh PNG có thể giúp giảm kích thước tệp.
Khi quyết định có tiếp tục chiến lược này hay không, bạn cần lưu ý việc giảm số lượng màu duy nhất một cách hiệu quả để áp dụng giai đoạn mã hóa có tổn thất cho hình ảnh. Tuy nhiên, một công cụ mã hóa có thể không đánh giá được mức độ xấu của một lỗi có vẻ nhỏ với mắt người. Do đó, bạn nên thực hiện thao tác này theo cách thủ công nhằm giúp đảm bảo sự cân bằng giữa việc nén hiệu quả và chất lượng hình ảnh được chấp nhận.
Có hai cách tiếp cận đặc biệt hữu ích mà bạn có thể thực hiện: cố gắng áp dụng các định dạng đã lập chỉ mục và áp dụng lượng tử vectơ.
Cố gắng duy trì các định dạng đã lập chỉ mục
Mọi nỗ lực giảm màu sắc đều bắt đầu bằng cách tối ưu hóa màu sắc của bạn, để có thể sử dụng định dạng INDEXED khi xuất hình ảnh dưới dạng PNG. Chế độ màu INDEXED hoạt động bằng cách chọn 256 màu tốt nhất để sử dụng và thay thế tất cả các giá trị pixel bằng chỉ mục vào bảng màu đó. Kết quả là số màu giảm từ 16 triệu (tiềm năng) xuống chỉ còn 256 màu: từ 3 (không có độ trong suốt) hoặc 4 (với độ trong suốt) byte trên mỗi pixel xuống 1 byte trên mỗi pixel. Sự thay đổi này sẽ làm giảm đáng kể kích thước tệp ở bước đầu tiên.
Hình 1 cho thấy một hình ảnh và biến thể được lập chỉ mục của hình ảnh đó.
![](https://developer.android.com/static/topic/performance/images/beforeafterindexed.png?hl=vi)
Hình 1. Hình ảnh trước và sau khi chuyển đổi sang định dạng INDEXED.
Hình 2 hiển thị bảng màu cho hình ảnh trong Hình 1:
![](https://developer.android.com/static/topic/performance/images/palette.png?hl=vi)
Hình 2. Bảng màu cho hình ảnh trong Hình 1.
Việc thể hiện hình ảnh của bạn dưới dạng hình ảnh có màu sẽ giúp cải thiện đáng kể kích thước tệp, vì vậy, bạn nên kiểm tra xem liệu phần lớn hình ảnh của bạn có thể chuyển đổi được hay không.
Dĩ nhiên, không phải mọi hình ảnh đều có thể được thể hiện chính xác chỉ bằng 256 màu. Ví dụ như một số hình ảnh có thể cần 257, 310, 512 hoặc 912 để màu hiển thị chính xác. Trong những trường hợp như vậy, việc định lượng vectơ cũng có thể hữu ích.
Phép lượng tử vector
Quá trình tạo hình ảnh được lập chỉ mục có thể được mô tả tốt hơn dưới dạng lượng tử vectơ (VQ). VQ đóng vai trò là một quá trình làm tròn cho các số có nhiều chiều. Trong quá trình này, tất cả các màu trong hình ảnh của bạn sẽ được nhóm dựa trên mức độ tương đồng. Đối với một nhóm nhất định, tất cả các màu trong nhóm đó sẽ được thay thế bằng một giá trị điểm giữa duy nhất, giúp giảm thiểu lỗi về màu trong ô đó (hoặc "trang web") nếu bạn đang sử dụng thuật ngữ Voronoi). Ở Hình 3, các chấm màu xanh lục biểu thị màu đầu vào, còn các chấm màu đỏ là các điểm giữ thay thế các màu đầu vào. Mỗi ô bị chặn bởi các đường màu xanh dương.
![](https://developer.android.com/static/topic/performance/images/vq.gif?hl=vi)
Hình 3. Áp dụng lượng tử vectơ cho các màu trong hình ảnh.
Kết quả của việc áp dụng VQ cho hình ảnh sẽ làm giảm số lượng màu duy nhất, thay thế từng nhóm màu bằng một màu duy nhất có "màu sắc gần gũi" về chất lượng hình ảnh.
Kỹ thuật này cũng cho phép bạn xác định số lượng màu duy nhất tối đa trong hình ảnh của bạn. Ví dụ như Hình 4 cho thấy đầu vẹt có 16,7 triệu màu (24 bit mỗi pixel hoặc bpp), cùng với một phiên bản chỉ cho phép sử dụng 16 (3 bpp) màu duy nhất.
![](https://developer.android.com/static/topic/performance/images/parrot.png?hl=vi)
Hình 4. Hình ảnh trước và sau khi áp dụng định lượng vectơ.
Bạn cũng có thể thấy ngay một sự giảm sút về chất lượng; hầu hết các màu gradient đã được thay thế, tạo nên hiệu ứng hình tròn cho hình ảnh. Hình ảnh này cần hơn 16 màu duy nhất.
Việc thiết lập một bước VQ trong quy trình có thể giúp bạn hiểu rõ hơn về số lượng màu duy nhất thực sự mà hình ảnh của bạn sử dụng, đồng thời giúp bạn giảm màu sắc một cách đáng kể . Bạn có thể sử dụng một số công cụ có sẵn để giúp triển khai kỹ thuật này.
JPG
Nếu đang sử dụng hình ảnh JPG, bạn có thể thực hiện một số thay đổi nhỏ để có thể tiết kiệm đáng kể kích thước tệp. Những phần này bao gồm:
- Tạo kích thước tệp nhỏ hơn thông qua nhiều phương thức mã hóa (mà không làm ảnh hưởng đến chất lượng).
- Điều chỉnh chất lượng một chút để mang lại khả năng nén tốt hơn.
Việc áp dụng các chiến lược này thường có thể giúp bạn giảm kích thước tệp tới 25%.
Khi chọn công cụ, hãy nhớ là các công cụ xuất ảnh có thể chèn siêu dữ liệu không cần thiết (chẳng hạn như thông tin GPS) vào hình ảnh của bạn. Ở mức tối thiểu, hãy cố gắng tận dụng các công cụ hiện có để giúp loại bỏ thông tin này khỏi tệp của bạn.
WebP
WebP là một định dạng hình ảnh mới hơn được hỗ trợ từ Android 4.2.1 (API cấp 17). Định dạng này cung cấp tính năng nén không tổn hao và hao tổn vượt trội đối với hình ảnh trên web. Khi sử dụng WebP, các nhà phát triển có thể tạo ra những hình ảnh nhỏ và phong phú hơn. Các tệp hình ảnh hao tổn WebP có kích thước trung bình nhỏ hơn 26% so với tệp PNG. Các tệp hình ảnh này cũng hỗ trợ độ trong suốt (hay còn được gọi là kênh alpha) với chi phí chỉ hơn 22% byte.
Hình ảnh có hao tổn WebP có kích thước nhỏ hơn 25-34% so với các hình ảnh JPG có thể so sánh ở các chỉ số chất lượng SSIM tương đương. Đối với các trường hợp khi nén RGB hao tổn được chấp nhận, thì WebP hao tổn cũng hỗ trợ độ trong suốt, thường tạo ra kích thước tệp nhỏ hơn 3 lần so với PNG.
Để biết thêm thông tin chi tiết về WebP, vui lòng truy cập trang web của WebP.
Bạn có thể chuyển đổi hình ảnh BMP, JPG, PNG hoặc GIF tĩnh hiện có sang định dạng WebP bằng Android Studio. Để biết thêm thông tin chi tiết, vui lòng xem bài viết Tạo hình ảnh WebP bằng Android Studio.
Chọn định dạng
Định dạng hình ảnh khác nhau phù hợp với các loại hình ảnh khác nhau. JPG và PNG có quy trình nén rất khác nhau, đồng thời cũng cho ra kết quả khá khác nhau.
Quyết định giữa PNG và JPG thường phụ thuộc vào độ phức tạp của hình ảnh. Hình 5 cho thấy hai hình ảnh xuất hiện khá khác nhau tùy thuộc vào sơ đồ nén nào nhà phát triển áp dụng. Hình ảnh ở bên trái có nhiều chi tiết nhỏ và do đó nén hiệu quả hơn bằng JPG. Hình ảnh bên phải, với các dòng cùng màu sẽ nén hiệu quả hơn bằng PNG.
![](https://developer.android.com/static/topic/performance/images/comparison.png?hl=vi)
Hình 5. Các trường hợp phù hợp cho JPG so với PNG
WebP là một định dạng có thể hỗ trợ cả chế độ hao tổn và không hao tổn, giúp định dạng này phù hợp với cả PNG và JPG. Điều duy nhất cần lưu ý là chế độ này chỉ hỗ trợ gốc trên các thiết bị chạy Android 4.2.1 (API cấp 17) trở lên. May mắn thay, hầu hết các thiết bị đều đáp ứng yêu cầu đó.
Hình 6 cung cấp hình ảnh trực quan đơn giản giúp bạn quyết định sử dụng giao thức nén nào.
![](https://developer.android.com/static/topic/performance/images/decisions.png?hl=vi)
Hình 6. Chọn sơ đồ nén
Xác định giá trị chất lượng tối ưu
Bạn có thể sử dụng một số kỹ thuật để đạt được sự cân bằng phù hợp giữa độ nén và chất lượng hình ảnh. Một kỹ thuật sử dụng các giá trị vô hướng và do đó chỉ hoạt động cho JPG và WebP. Một kỹ thuật khác tận dụng thư viện Butteraugli và có thể sử dụng được cho mọi định dạng hình ảnh.
Giá trị vô hướng (chỉ JPG và WebP)
Sức mạnh của JPG và WebP xuất phát từ thực tế là bạn có thể sử dụng giá trị vô hướng để cân bằng chất lượng với kích thước tệp. Bí quyết là tìm ra giá trị chất lượng phù hợp cho hình ảnh của bạn. Mức chất lượng quá thấp sẽ tạo ra một tệp nhỏ với chi phí chất lượng hình ảnh. Mức chất lượng quá cao sẽ làm tăng kích thước tệp mà không mang lại lợi ích đáng kể cho người dùng.
Giải pháp đơn giản nhất là chọn một giá trị không tối đa và sử dụng giá trị đó. Tuy nhiên, vui lòng lưu ý giá trị chất lượng sẽ ảnh hưởng khác nhau đến từng hình ảnh. Chẳng hạn như mặc dù chất lượng là 75% có thể ổn trên hầu hết các hình ảnh, nhưng có thể tồn tại một số trường hợp không liên quan. Bạn nên đảm bảo thử nghiệm giá trị tối đa đã chọn so với mẫu hình ảnh đại diện. Ngoài ra, hãy đảm bảo thực hiện tất cả các thử nghiệm với hình ảnh gốc, chứ không phải trên các phiên bản được nén.
Đối với các ứng dụng có nội dung nghe nhìn lớn được tải lên và gửi lại hàng triệu JPG mỗi ngày, việc điều chỉnh thao tác cho từng thành phần là không thực tế. Bạn có thể giải quyết thách thức này bằng cách chỉ định một số mức chất lượng khác nhau, tùy theo danh mục hình ảnh. Ví dụ như bạn có thể đặt 35% làm chế độ cài đặt chất lượng cho hình thu nhỏ, vì hình ảnh nhỏ hơn sẽ ẩn thêm nhiều cấu phần nén.
Butteraugli
Dự án Butteraugli là một thư viện để kiểm tra Ngưỡng lỗi tâm lý của hình ảnh: điểm mà người xem bắt đầu nhận thấy sự suy giảm về chất lượng của hình ảnh. Nói cách khác, dự án này sẽ cố gắng định lượng mức độ biến dạng của hình ảnh nén.
Butteraugli cho phép bạn xác định mục tiêu cho chất lượng hình ảnh, sau đó chạy các tệp nén PNG, JPG hao tổn và WebP không hao tổn. Sau đó, bạn có thể chọn hình ảnh đó là sự cân bằng tốt nhất giữa kích thước tệp và cấp độ Butteraugli. Hình 7 cho thấy một ví dụ về cách đã sử dụng Butteraugli để tìm mức chất lượng JPG tối thiểu trước khi hình ảnh bị méo ở mức người dùng có thể nhận ra vấn đề; kết quả là kích thước tệp giảm khoảng 65%.
![](https://developer.android.com/static/topic/performance/images/moarparrots.png?hl=vi)
Hình 7. Hình ảnh trước và sau khi áp dụng công nghệ Butteraugli.
Butteraugli cho phép bạn tiếp tục dựa trên đầu ra hoặc đầu vào. Tức là, bạn có thể tìm chế độ cài đặt chất lượng thấp nhất trước khi người dùng nhận thấy mức độ biến dạng đáng chú ý trong hình ảnh thu được, hoặc bạn có thể đặt mức độ biến dạng hình ảnh lặp lại để tìm hiểu các mức chất lượng liên quan.
Kích cỡ phân phát
Thật lý tưởng khi chỉ giữ một độ phân giải duy nhất của hình ảnh trên máy chủ. Khi một thiết bị truy cập vào hình ảnh, máy chủ sẽ phân phát hình ảnh đó ở một độ phân giải và để giảm quy mô tỷ lệ cho thiết bị.
Giải pháp này thuận tiện cho nhà phát triển, nhưng có thể gây khó chịu cho người dùng, vì nó buộc người dùng phải tải xuống nhiều dữ liệu hơn mức họ cần. Thay vào đó, bạn nên lưu trữ nhiều kích thước hình ảnh và phân phát kích thước phù hợp nhất cho một trường hợp sử dụng cụ thể. Ví dụ như đối với hình thu nhỏ, việc phân phát hình thu nhỏ thực tế thay vì phân phát và giảm kích thước của phiên bản có kích thước đầy đủ sẽ tốn ít băng thông mạng hơn
Phương pháp này phù hợp với tốc độ tải xuống và ít tốn kém hơn cho những người dùng có thể đang sử dụng gói dữ liệu có giới hạn hoặc có đo lượng dữ liệu. Nếu bạn tiếp tục thao tác này, hình ảnh sẽ chiếm ít dung lượng hơn trên thiết bị và bộ nhớ chính. Trong trường hợp hình ảnh lớn, chẳng hạn như hình ảnh 4K, phương pháp này cũng giúp thiết bị không phải thay đổi kích thước các hình ảnh trước khi tải.
Việc triển khai phương pháp này yêu cầu bạn phải có dịch vụ hình ảnh phụ trợ để cung cấp hình ảnh ở nhiều độ phân giải với bộ nhớ đệm phù hợp. Hiện có các dịch vụ có thể trợ giúp về việc này. Ví dụ như App Engine với chức năng đổi kích thước hình ảnh đã được cài đặt.