Tìm màu "tương đương" với độ mờ


92

Giả sử tôi có màu nền với một "dải băng" chạy trên nó bằng một màu đồng nhất khác. Bây giờ, tôi muốn dải băng trong suốt một phần để cho một số chi tiết hòa trộn với nhau, nhưng vẫn giữ dải băng "cùng màu" trên nền.

Có cách nào để (dễ dàng) xác định, đối với độ mờ / alpha <100% của màu dải băng nhất định, giá trị RGB nào mà nó phải giống với màu của nó với độ mờ 100% trên nền?

Đây là một hình ảnh. Nền là rgb(72, 28, 97), dải băng rgb(45, 34, 70). Tôi muốn một rgba(r, g, b, a)dải ruy-băng để nó có vẻ giống với màu đồng nhất này.

nhập mô tả hình ảnh ở đây


1
Bạn có thể tìm thấy một câu hỏi tương tự tại đây: stackoverflow.com/questions/6672374/convert-rgb-rgba nhưng điểm khác biệt chính là câu hỏi đó chỉ định màu cơ bản là trắng, trong khi câu hỏi này là tùy ý.
BoltClock

Câu trả lời:


129

Pha trộn màu chỉ là một nội suy tuyến tính trên mỗi kênh, phải không? Vì vậy, phép toán khá đơn giản. Nếu bạn có RGBA1 trên RGB2, kết quả hình ảnh hiệu quả RGB3 sẽ là:

r3 = r2 + (r1-r2)*a1
g3 = g2 + (g1-g2)*a1
b3 = b2 + (b1-b2)*a1

… Trong đó kênh alpha từ 0,0 đến 1,0.

Kiểm tra tình trạng: nếu alpha là 0, RGB3 có giống RGB2 không? Đúng. Nếu alpha là 1, RGB3 có giống RGB1 không? Đúng.

Nếu bạn chỉ khóa màu nền và màu cuối cùng, thì có một số lượng lớn màu RGBA (vô hạn, trong không gian dấu phẩy động) có thể đáp ứng yêu cầu. Vì vậy, bạn phải chọn màu của thanh hoặc mức độ mờ mà bạn muốn, và tìm ra giá trị của cái kia.

Chọn màu dựa trên Alpha

Nếu bạn biết RGB3 (màu mong muốn cuối cùng), RGB2 (màu nền) và A1 (độ mờ bạn muốn) và bạn chỉ đang tìm RGB1, thì chúng tôi có thể sắp xếp lại các phương trình như sau:

r1 = (r3 - r2 + r2*a1)/a1
g1 = (g3 - g2 + g2*a1)/a1
b1 = (b3 - b2 + b2*a1)/a1

Về mặt lý thuyết, có một số kết hợp màu là có thể, nhưng không thể với dải RGBA tiêu chuẩn. Ví dụ: nếu nền là màu đen tuyền, màu cảm nhận mong muốn là màu trắng tinh khiết và alpha mong muốn là 1%, thì bạn sẽ cần:

r1 = g1 = b1 = 255/0.01 = 25500

… Một màu trắng siêu sáng 100 × sáng hơn bất kỳ màu nào hiện có.

Chọn Alpha dựa trên màu sắc

Nếu bạn biết RGB3 (màu mong muốn cuối cùng), RGB2 (màu nền) và RGB1 (màu bạn có mà bạn muốn thay đổi độ mờ) và bạn chỉ đang tìm A1, thì chúng tôi có thể sắp xếp lại do đó, các phương trình:

a1 = (r3-r2) / (r1-r2)
a1 = (g3-g2) / (g1-g2)
a1 = (b3-b2) / (b1-b2)

Nếu những giá trị này cung cấp các giá trị khác nhau, thì bạn không thể làm cho nó khớp chính xác, nhưng bạn có thể tính trung bình các alpha để đến gần nhất có thể. Ví dụ, không có độ mờ nào trên thế giới cho phép bạn đặt màu xanh lá cây lên màu đỏ để có được màu xanh lam.


Không phải là r1, g1b1cũng chưa biết?
Eric

@Eric Tôi không chắc. Tôi đã chỉnh sửa câu trả lời trong trường hợp đó là mức alpha đã được biết đến và các màu thì không.
Phrogz

Lưu ý, tôi đã sử dụng ba công thức đầu tiên của bạn trong Photoshop để tìm màu sẽ là 0,8 alpha khi màu tham chiếu khác duy nhất của tôi là màu trắng ... Tôi phải sử dụng 1 + (1 - a) hoặc 1,2 để tìm đúng màu ...
John William Domingo

1
@Phrogz Tôi đang sử dụng phương trình 'Chọn màu dựa trên Alpha' của bạn và tôi nhận được một số âm (-31) cho kênh màu đỏ. Khi tôi sử dụng giá trị âm làm giá trị màu đỏ, tôi nhận được kết quả giống như thể tôi đã sử dụng 0 làm giá trị màu đỏ. Có cách nào để chuyển đổi tiêu cực này thành một cái gì đó có thể sử dụng được không? Bất kỳ manh mối nào về những gì đang xảy ra ở đây?
Nocturno

Có thể các tính toán của tôi bị tắt, nhưng công thức này tạo ra kết quả không mong muốn khi RGB3 = # 163920, RGB2 = #FFFFFF và A1 = 0,92; RGB1 được tính toán = rgb (2, 40, 13), nhưng rgba (2, 40, 13, 0,92) = # 15381F, không phải # 163920.
thdoan

12

tôi đã tạo một bản mixin ÍT NHẤT bằng câu trả lời của Phrogz. bạn nhập:

  1. màu sắc nên trông như thế nào
  2. với một alpha nhất định
  3. trên một nền nhất định (mặc định là màu trắng)

Đây là mã:

.bg_alpha_calc (@desired_colour, @desired_alpha, @background_colour: white) {
    @r3: red(@desired_colour);
    @g3: green(@desired_colour);
    @b3: blue(@desired_colour);

    @r2: red(@background_colour);
    @g2: green(@background_colour);
    @b2: blue(@background_colour);

    // r1 = (r3 - r2 + r2 * a1) / a1
    @r1: ( @r3 - @r2 + (@r2 * @desired_alpha) ) / @desired_alpha;
    @g1: ( @g3 - @g2 + (@g2 * @desired_alpha) ) / @desired_alpha;
    @b1: ( @b3 - @b2 + (@b2 * @desired_alpha) ) / @desired_alpha;

    background-color: @desired_colour;
    background-color: rgba(@r1, @g1, @b1, @desired_alpha);

}

Cách sử dụng như vậy:

@mycolour: #abc;
@another_colour: blue;
.box_overlay {
  // example:
  .bg_alpha_calc (@mycolour, 0.97, @another_colour);
  // or (for white bg) just:
  .bg_alpha_calc (@mycolour, 0.97);
}

Rõ ràng là không hoạt động đối với các kết hợp bất khả thi (như Phrogz đã đề cập), điều đó có nghĩa là chỉ hỗ trợ mức độ minh bạch nhẹ. Xem cách bạn đi với nó.


1
@mixin bg_alpha_calc ($ wish_colour, $ wish_alpha, $ background_colour: trắng) {$ r3: red ($ wish_colour); $ g3: màu xanh lá cây ($ màu sắc mong muốn); $ b3: xanh lam ($ màu sắc mong muốn); $ r2: đỏ ($ background_colour); $ g2: xanh lục ($ background_colour); $ b2: blue ($ background_colour); // r1 = (r3 - r2 + r2 * a1) / a1 $ r1: ($ r3 - $ r2 + ($ r2 * $ mong muốn_alpha)) / $ mong muốn_alpha; $ g1: ($ g3 - $ g2 + ($ g2 * $ mong muốn_alpha)) / $ mong muốn_alpha; $ b1: ($ b3 - $ b2 + ($ b2 * $ mong muốn_alpha)) / $ mong muốn_alpha; background-color: $ mong muốn_ màu; background-color: rgba ($ r1, $ g1, $ b1, $ mong muốn_alpha); }
metaColin

2
Tôi đã thông qua và tạo một bản mixin phiên bản SCSS. Tìm bản trình diễn và mã tại đây: codepen.io/Grienauer/pen/Grogdx
Grienauer

@Grienauer Tôi cũng làm như vậy, không nhận ra bạn đã chia sẻ nó rồi! Sự khác biệt duy nhất của tôi là tôi mặc định màu nền sang màu trắng
tehlivi

7

Nhờ Phrogz 's và ephemer ' s câu trả lời tuyệt vời, đây là một chức năng Sass rằng Automagically tính màu RGBA tương đương tốt nhất.

Bạn gọi nó với màu mong muốn và nền hiện có, và nó sẽ tính toán màu RGBA tương đương tốt nhất (nghĩa là trong suốt nhất) mang lại kết quả mong muốn trong phạm vi ± 1/256 của mỗi thành phần RGB (do lỗi làm tròn):

@function alphaize($desired-color, $background-color) {

    $r1: red($background-color);
    $g1: green($background-color);
    $b1: blue($background-color);

    $r2: red($desired-color);
    $g2: green($desired-color);
    $b2: blue($desired-color);

    $alpha: 0;
    $r: -1;
    $g: -1;
    $b: -1;

    @while $alpha < 1 and ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255) {
        $alpha: $alpha + 1/256;
        $inv: 1 / $alpha;
        $r: $r2 * $inv + $r1 * (1 - $inv);
        $g: $g2 * $inv + $g1 * (1 - $inv);
        $b: $b2 * $inv + $b1 * (1 - $inv);
    }

    @return rgba($r, $g, $b, $alpha);
}

Tôi vừa thử nghiệm nó với một số sự kết hợp (tất cả các chủ đề của Bootswatch) và nó hoạt động tốt, cho cả kết quả tối trên ánh sáng và sáng tối.

Tái bút: Nếu bạn cần độ chính xác cao hơn ± 1/256 cho màu kết quả, bạn sẽ cần biết loại trình duyệt thuật toán làm tròn nào áp dụng khi pha trộn màu rgba (tôi không biết liệu đó có được chuẩn hóa hay không) và thêm một điều kiện hiện có @while, để nó tiếp tục tăng $alphacho đến khi đạt được độ chính xác mong muốn.


2
FYI, chức năng này tồn tại trong Stylus dưới dạng transparentify(): stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ... mà tôi đã phát hiện ra sau khi chuyển nó theo cách thủ công sang Stylus ...
weotch

6

Từ câu trả lời của @Phrogz:

r3 = r2 + (r1-r2)*a1
g3 = g2 + (g1-g2)*a1
b3 = b2 + (b1-b2)*a1

Vì thế:

r3 - r2 = (r1-r2)*a1
g3 - g2 = (g1-g2)*a1
b3 - b2 = (b1-b2)*a1

Vì thế:

r1 = (r3 - r2) / a1 + r2
g1 = (g3 - g2) / a1 + g2
b1 = (b3 - b2) / a1 + b2

Lưu ý bạn có thể chọn bất kỳ giá trị a1, và điều này sẽ tìm các giá trị tương ứng của r1, g1b1yêu cầu. Ví dụ: chọn alpha là 1 cho bạn biết rằng bạn cần RGB1 = RGB3, nhưng chọn alpha 0 thì không có giải pháp nào (hiển nhiên).


1

Giải pháp thiết thực nhất mà tôi tìm thấy cho đến nay: chỉ cần đo màu kết quả bằng công cụ chọn màu và sau đó sử dụng màu đã đo cho lớp phủ. Phương pháp này cho màu sắc hoàn hảo.

Tôi đã thử sử dụng các hỗn hợp khác nhau nhưng do lỗi làm tròn, tôi vẫn có thể thấy sự khác biệt bằng mắt thường


1
OP có lẽ muốn một cách để xác định động, nhưng điều đó không được nêu cụ thể và câu trả lời của bạn thực sự đưa ra một bản hack tốt cho các lựa chọn màu tĩnh / alpha.
Erik Knowles

0

Để mở rộng câu trả lời của @ Tobia và cho phép chỉ định độ mờ giống như minh bạch hóa:

@function rgbaMorph($desired-color, $background-color: rgb(255,255,255), $desired-alpha: 0) {

    $r1: red($desired-color);
    $g1: green($desired-color);
    $b1: blue($desired-color);

    $r2: red($background-color);
    $g2: green($background-color);
    $b2: blue($background-color);

    $r: -1;
    $g: -1;
    $b: -1;

    @if ($desired-alpha != 0) {
        $r: ( $r1 - $r2 + ($r2 * $desired-alpha) ) / $desired-alpha;
        $g: ( $g1 - $g2 + ($g2 * $desired-alpha) ) / $desired-alpha;
        $b: ( $b1 - $b2 + ($b2 * $desired-alpha) ) / $desired-alpha;
    }

    @if (($desired-alpha == 0) or ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255)) {
        //if alpha not attainable, this will find lowest alpha that is

        $alpha: $desired-alpha;
        @while $alpha < 1 and ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255) {
            $alpha: $alpha + 1/256;
            $inv: 1 / $alpha;
            $r: $r1 * $inv + $r2 * (1 - $inv);
            $g: $g1 * $inv + $g2 * (1 - $inv);
            $b: $b1 * $inv + $b2 * (1 - $inv);
        }
        @debug "Color not attainable at opacity using alpha: " $alpha " instead of: " $desired-alpha;

        $desired-alpha: $alpha;
    }

    @return rgba($r, $g, $b, $desired-alpha);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.