Tôi đã trả lời một câu hỏi tương tự trên Exchange Development Stack Exchange một lúc trước, vì vậy hãy để tôi tóm tắt các câu trả lời ở đó.
Bạn có ý tưởng chọn màu đen hoặc trắng, tùy theo màu nào tương phản tốt hơn với màu nền, là âm thanh. Tuy nhiên, chỉ cần lấy trung bình các thành phần RGB sẽ không cho thấy dấu hiệu rõ ràng về việc một màu sắc cụ thể sẽ xuất hiện như thế nào đối với mắt người, vì (hầu hết) hai lý do:
Trước hết, vì những lý do liên quan đến nhận thức màu sắc của con người, các kênh màu đỏ, xanh lá cây và xanh dương không có độ chói tương đối giống nhau ; trong thực tế, màu xanh lam thuần khiết ( #0000ff
) chỉ sáng khoảng 10% (và màu đỏ thuần chỉ khoảng 30% như màu sáng) so với màu xanh lá cây thuần khiết ( #00ff00
). Do đó, ví dụ văn bản màu đen trên màu xanh thuần khiết sẽ không bao giờ có độ tương phản đặc biệt tốt.
Ví dụ, những hình ảnh dưới đây cho thấy ví dụ về văn bản màu đen và màu trắng trên màu đỏ tinh khiết, màu xanh lá cây và hình nền màu xanh ( #ff0000
, #00ff00
và #0000ff
):
Bạn có thể thấy rõ sự khác biệt về độ tương phản, mặc dù tất cả các màu này có cùng giá trị RGB trung bình.
Sự phức tạp khác là các không gian màu RGB thường được sử dụng trên màn hình máy tính (như sRGB ) không phải là tuyến tính, nhưng có gamma hiển thị khoảng 2 hoặc hơn. Điều đó có nghĩa là, ví dụ như màu RGB #7f7f7f
= "50% màu xám" không thực sự xuất hiện một nửa sáng như màu trắng tinh khiết ( #ffffff
), mà chỉ sáng hơn khoảng 25%, trong khi màu thực sự có độ sáng tương đối giữa một nửa màu đen và trắng là thực sự gần hơn với "75% màu xám" ( #bfbfbf
).
Tuy nhiên, thuận tiện, mắt người cũng không tuyến tính và nhạy cảm hơn với sự khác biệt trong các màu tối hơn. Trong thực tế, đối với các sắc thái của màu xám, các phi tuyến tính gần như bị loại bỏ, do đó, RGB 50% màu xám ( #7f7f7f
) vẫn còn nhận thức về khoảng cách tương đương với cả hai màu đen và trắng. Như một cuộc biểu tình, đây là một số văn bản màu đen và trắng trên 25%, 50% và 75% nền xám ( #3f3f3f
, #7f7f7f
và #bfbfbf
):
Tuy nhiên, để tính toán chính xác độ chói của màu RGB tùy ý, chúng ta cần tính đến gamma hiển thị, vì đó là giá trị độ chói tuyến tính cần được tính trung bình.
Để kết hợp tất cả lại với nhau, để xác định xem văn bản đen hay trắng sẽ có độ tương phản tốt hơn trên nền, bạn cần phải:
- chuyển đổi các giá trị màu RGB được nén bằng gamma thành RGB tuyến tính,
- lấy trung bình trọng số của các thành phần R, G và B tuyến tính, và
- so sánh trung bình kết quả với một ngưỡng phù hợp.
Giá trị ngưỡng cho kết quả tốt nhất có thể được xác định bằng thực nghiệm, nhưng nhìn chung người ta sẽ mong đợi nó nằm gần với độ chói của màu xám 50% RGB. Trong mọi trường hợp, đáng chú ý là độ tương phản cảm nhận sẽ khác nhau tùy thuộc vào cài đặt hiển thị của người xem và điều kiện xem, do đó, không có giá trị tối ưu duy nhất cho mọi người, mà là một phạm vi khá rộng các lựa chọn tốt hơn hoặc ít hơn.
Nếu bạn chỉ muốn một công thức đơn giản để cắm số vào, hãy thử điều này:
- nếu 0,2126 × R γ + 0,7152 × G γ + 0,0722 × B γ > 0,5 γ , chọn màu đen; khác chọn màu trắng,
nơi γ là giá trị gamma màn hình xấp xỉ ( γ = 2,2 là điển hình).
Đối với một xấp xỉ thậm chí đơn giản hơn, bạn có thể bỏ qua hiệu chỉnh gamma (nghĩa là giả sử một cách hiệu quả rằng γ = 1) và chỉ cần sử dụng điều kiện 0.2126 × R + 0.7152 × G + 0.0722 × B > 0.5. Đối với các sắc thái của màu xám, điều này sẽ không có sự khác biệt (vì chúng ta đang áp dụng cùng một gamma cho cả hai mặt của bất đẳng thức), nhưng nó phần nào đánh giá quá cao độ chói của các màu bão hòa. May mắn thay, trên các màu như vậy, cả hai màu đen và trắng thường có độ tương phản tốt, do đó, lỗi có thể không quan trọng trong thực tế.
Cuối cùng, lưu ý rằng, nếu màu nền không đồng nhất, có thể không có màu văn bản nào có thể trông đẹp. Trong những trường hợp như vậy, bạn có thể xem xét, ví dụ như sử dụng văn bản màu đen với đường viền màu trắng hoặc ngược lại hoặc có thể bao quanh văn bản của bạn với hộp bán trong suốt có màu đối diện.