Hướng dẫn mix colors javascript - pha trộn màu sắc javascript

Tôi đã chuyển đổi mã của nó thành Objective-C và xác minh nó hoạt động như mô tả.

ArtColors sẽ cung cấp một cuộc gọi chức năng đơn giản trộn lẫn hai màu theo cách thực tế với tối thiểu mã, chỉ lấy hai đầu vào RGB và tỷ lệ pha trộn, như thế này:

Return Color=SubtractiveMix(Color a, Color b, percentage)

ArtColors sử dụng một thuật toán mà (tôi nghĩ) cho kết quả khá tốt với một phần của mã của các phương thức khác và không cần tính toán hoặc lưu trữ dữ liệu phản xạ hoặc các công thức phức tạp tính toán. Mục tiêu là 80% hiện thực chỉ với 20% mã.

Cách tiếp cận cơ bản được lấy cảm hứng bằng cách xem xét cách sơn thực sự trộn. Kiểm tra cận cảnh của sơn trộn:

Hướng dẫn mix colors javascript - pha trộn màu sắc javascript

Nếu bạn nhìn cẩn thận, bạn có thể thấy rằng ở một số khu vực, hai loại sơn được pha trộn hoàn toàn và kết quả là trừ: vàng và xanh lam đang tạo ra màu xanh đậm hơn nhiều. Màu đỏ và màu xanh đang làm một màu tím rất tối. Tuy nhiên, ở các khu vực khác, nơi mà sự pha trộn không quá kỹ lưỡng, các vệt màu vàng và xanh tồn tại cạnh nhau. Những loại sơn này phản chiếu ánh sáng vàng và xanh. Ở một khoảng cách xa, những màu này được trộn lẫn với mắt khi các vòng xoáy xa cách quá nhỏ để được nhìn thấy.

Hãy xem xét thêm rằng sơn trộn là một hỗn hợp theo nghĩa hóa học: không có thay đổi hóa học xảy ra. Các phân tử màu đỏ và màu xanh vẫn còn đó trong sự pha trộn kỹ lưỡng, làm chính xác những gì chúng đang làm khi tách biệt: phản chiếu ánh sáng đỏ và xanh. Chỉ có rất nhiều hiệu ứng vật lý dưới bề mặt đang diễn ra khi ánh sáng nảy xung quanh trong môi trường. Ánh sáng sự cố được hấp thụ và phản xạ bởi một phân tử, và sau đó bởi một phân tử khác, và cuối cùng kết quả phản ánh ra mắt.

Làm thế nào điều này giúp giải quyết vấn đề của chúng tôi?

Các cách tiếp cận trừ nghiêm ngặt bắt đầu với màu trắng, và sau đó trừ các giá trị RGB của màu A và màu B từ màu trắng, và trả lại những gì còn lại. Cách tiếp cận này thường quá tối. Tại sao? Một số sắc tố vẫn đang phản ánh màu sắc đặc biệt của nó trên một quy mô nhỏ. Nếu chúng ta thực hiện một cách tiếp cận là một phần phụ gia, một phần trừ, chúng ta sẽ nhận được một kết quả thực tế hơn!

Hơn nữa, nếu màu a = màu B, chức năng của chúng tôi sẽ trả về cùng màu đó. Trộn cùng một màu với cùng một màu nên bằng cùng một màu! Sử dụng thuật toán trừ nghiêm ngặt, kết quả là phiên bản tối hơn của màu sắc gốc (vì các giá trị màu đầu vào bị trừ khỏi màu trắng hai lần). Càng càng gần hai màu đầu vào, càng ít thay đổi trong hỗn hợp.

Mã ArtColor để trộn trừ là:

Color ColorMixSub(Color a, Color b, float blend) {
    Color out;
    Color c,d,f;

    c=ColorInv(a);
    d=ColorInv(b);

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

    float cd=ColorDistance(a,b);
    cd=4.0*blend*(1.0-blend)*cd;
    out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);

    out.a=255;
return out;
}

Giải thích về mã: Color aColor b là màu đầu vào. blend chỉ định số lượng mỗi màu để pha trộn, từ 0 đến 1.0, giống như một phép nội suy tuyến tính (LERP). 0,0 = tất cả màu a, 1.0 = tất cả màu B. 0,5 = 50% -50% hỗn hợp A và B.

Đầu tiên chúng ta tìm thấy các nghịch đảo RGB của màu A và B, và gán chúng cho các màu mới c và d.

    c=ColorInv(a);
    d=ColorInv(b);

Sau đó, chúng tôi trừ cả C và D từ RGB trắng tinh khiết, kẹp kết quả thành 0 và gán kết quả cho màu f.

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

Cho đến nay, F là kết quả hoàn toàn trừ, gặp phải các vấn đề được đề cập ở trên.

Tiếp theo, chúng tôi tính toán "khoảng cách màu" giữa màu A và màu B, chỉ là khoảng cách vectơ giữa chúng trong không gian RGB, được chuẩn hóa giữa 0,0 (màu giống hệt nhau) và 1.0 (hoàn toàn đối diện, như màu trắng và đen).

float cd=ColorDistance(a,b);

Giá trị này sẽ giúp giải quyết vấn đề trộn hai màu tương tự không nên thay đổi kết quả rất nhiều. Hệ số khoảng cách màu

Color ColorMixSub(Color a, Color b, float blend) {
    Color out;
    Color c,d,f;

    c=ColorInv(a);
    d=ColorInv(b);

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

    float cd=ColorDistance(a,b);
    cd=4.0*blend*(1.0-blend)*cd;
    out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);

    out.a=255;
return out;
}
0 sau đó được chuyển đổi bởi một hàm chuyển bậc hai, điều chỉnh mức độ trộn lẫn phụ và phụ gia chúng ta làm:

cd=4.0*blend*(1.0-blend)*cd;

Hướng dẫn mix colors javascript - pha trộn màu sắc javascript

Các điểm cuối đảm bảo rằng tỷ lệ phần trăm pha trộn gần 0% hoặc 100% trông rất gần với màu đầu vào ban đầu. Đường cong bậc hai cho một gam màu tốt cho sự pha trộn tiếp theo. Đỉnh của đường cong được xác định bởi khoảng cách màu. Đầu ra của chức năng này xác định lượng phụ gia so với sự pha trộn trừ trong kết quả của chúng tôi. Các màu xa hơn sẽ pha trộn với động lực trừ phụ hơn (hoàn toàn trừ ở y = 1.0). Màu sắc tương tự hòa trộn với động lực phụ gia hơn (đường cong phẳng hơn) vẫn có yếu tố trừ. Tối đa của hàm truyền bậc hai là khoảng cách màu được chuẩn hóa, do đó màu đối lập bằng cách đối lập trong không gian màu sẽ pha trộn hoàn toàn một cách hoàn toàn.

Dòng cuối cùng thực hiện tất cả các công việc:

out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);`

Đầu tiên, chúng tôi trộn thêm màu A và màu B trong tỷ lệ ____99 được chỉ định, được thực hiện bởi

Color ColorMixSub(Color a, Color b, float blend) {
    Color out;
    Color c,d,f;

    c=ColorInv(a);
    d=ColorInv(b);

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

    float cd=ColorDistance(a,b);
    cd=4.0*blend*(1.0-blend)*cd;
    out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);

    out.a=255;
return out;
}
2. Điều này thể hiện hiệu ứng pha trộn phụ gia của những vòng xoáy tốt trong hình ảnh trên và tương tác dưới bề mặt. Sự vắng mặt của yếu tố này có thể là nơi một cách tiếp cận trừ nghiêm ngặt mang lại kết quả lẻ. Kết quả phụ gia này sau đó được pha trộn với kết quả trừ hoàn toàn của chúng tôi
Color ColorMixSub(Color a, Color b, float blend) {
    Color out;
    Color c,d,f;

    c=ColorInv(a);
    d=ColorInv(b);

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

    float cd=ColorDistance(a,b);
    cd=4.0*blend*(1.0-blend)*cd;
    out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);

    out.a=255;
return out;
}
3, theo hàm chuyển được đề cập ở trên, dựa trên khoảng cách màu giữa Color aColor b.

Voila!Một kết quả khá tốt xảy ra cho một loạt các màu đầu vào.