불투명도가있는 "동등한"색상 찾기


93

"리본"이 다른 단색으로 실행되는 배경색이 있다고 가정 해 보겠습니다. 이제 리본을 부분적으로 투명하게하여 일부 세부 사항이 혼합되도록하지만 배경 위에 리본을 "동일한 색상"으로 유지합니다.

주어진 불투명도 / 알파가 리본 색상의 100 % 미만인 경우 배경 위에 100 % 불투명도를 가진 색상과 동일해야하는 RGB 값을 (쉽게) 결정할 수있는 방법이 있습니까?

여기 사진이 있습니다. 배경은 rgb(72, 28, 97)리본 rgb(45, 34, 70)입니다. rgba(r, g, b, a)이 단색과 동일하게 보이도록 리본을 위해를 원합니다 .

여기에 이미지 설명 입력


1
매우 유사한 질문은 다음에서 찾을 수 있습니다. stackoverflow.com/questions/6672374/convert-rgb-rgba 그러나 주요 차이점은 해당 질문이 기본 색상을 흰색으로 지정하지만이 질문은 임의적이라는 것입니다.
BoltClock

답변:


131

색상 혼합은 채널당 선형 보간입니다. 따라서 수학은 매우 간단합니다. RGB2보다 RGBA1이있는 경우 효과적인 시각적 결과 RGB3은 다음과 같습니다.

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

… 알파 채널은 0.0에서 1.0까지입니다.

온 전성 검사 : 알파가 0이면 RGB3이 RGB2와 같습니까? 예. 알파가 1이면 RGB3이 RGB1과 동일합니까? 예.

배경색과 최종 색상 만 잠근 경우 요구 사항을 충족 할 수있는 RGBA 색상 (무한, 부동 소수점 공간)이 많이 있습니다. 따라서 막대의 색상이나 원하는 불투명도 수준을 선택하고 다른 값을 찾아야합니다.

알파를 기반으로 색상 선택

RGB3 (마지막 원하는 색상), RGB2 (배경색) 및 A1 (원하는 불투명도)을 알고 있고 RGB1을 찾고 있다면 그에 따라 방정식을 다시 정렬 할 수 있습니다.

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

이론적으로는 가능하지만 표준 RGBA 범위에서는 불가능한 몇 가지 색상 조합이 있습니다. 예를 들어 배경이 순수한 검정이고 원하는 인식 색상이 순수한 흰색이고 원하는 알파가 1 % 인 경우 다음이 필요합니다.

r1 = g1 = b1 = 255/0.01 = 25500

… 사용 가능한 어떤 것보다 100 배 더 밝은 매우 밝은 흰색.

색상을 기반으로 알파 선택

RGB3 (마지막 원하는 색상), RGB2 (배경색) 및 RGB1 (불투명도를 변경하려는 색상)을 알고 있고 A1을 찾고있는 경우에는 다음을 다시 정렬 할 수 있습니다. 따라서 방정식 :

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

이들이 다른 값을 제공하는 경우 정확히 일치시킬 수는 없지만 가능한 한 가까워 지도록 알파의 평균을 낼 수 있습니다. 예를 들어, 파란색을 얻기 위해 빨간색 위에 녹색을 놓을 수있는 불투명도는 세상에 없습니다.


하지 않습니다 r1, g1그리고 b1알 수없는도?
에릭

@Eric 확실하지 않습니다. 알려진 알파 레벨과 그렇지 않은 색상 인 경우 답변을 편집했습니다.
Phrogz

참고로, Photoshop에서 처음 세 가지 공식을 사용하여 유일한 다른 참조 색상이 흰색 일 때 0.8 알파에서 색상이 무엇인지 확인했습니다. 올바른 색상 ...
John William Domingo

1
@Phrogz 저는 '알파에 따라 색상 선택'방정식을 사용하고 있으며 빨간색 채널에 대해 음수 (-31)를 얻습니다. 음수를 빨간색 값으로 사용하면 0을 빨간색 값으로 사용한 것과 같은 결과를 얻습니다. 이 네거티브를 유용한 것으로 변환하는 방법이 있습니까? 여기서 무슨 일이 일어나고 있는지에 대한 단서가 있습니까?
Nocturno

내 계산이 꺼져있을 수도 있지만이 공식은 RGB3 = # 163920, RGB2 = #FFFFFF 및 A1 = 0.92 일 때 예기치 않은 결과를 생성합니다. 계산 된 RGB1 = rgb (2, 40, 13)이지만 rgba (2, 40, 13, 0.92) = # 15381F, # 163920이 아닙니다.
thdoan dec

12

나는 Phrogz의 대답을 사용하여 적은 믹스 인을 만들었습니다. 당신은 입력 :

  1. 색상이 어떻게 보일까요
  2. 특정 알파로
  3. 주어진 배경에 (기본값은 흰색)

코드는 다음과 같습니다.

.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);

}

이렇게 사용법 :

@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);
}

분명히 불가능한 조합 (Phrogz에서 언급했듯이)에는 작동하지 않습니다. 즉, 약간의 투명도 만 지원됩니다. 당신이 그것으로 어떻게 가는지보십시오.


1
@mixin bg_alpha_calc ($ desired_colour, $ desired_alpha, $ background_colour : 흰색) {$ r3 : red ($ desired_colour); $ g3 : 녹색 ($ desired_colour); $ b3 : 파랑 ($ desired_colour); $ r2 : 빨강 ($ background_colour); $ g2 : 녹색 ($ background_colour); $ b2 : 파랑 ($ 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; 배경색 : $ desired_colour; 배경색 : rgba ($ r1, $ g1, $ b1, $ desired_alpha); }
metaColin

2
SCSS 버전 믹스 인을 채택하여 만들었습니다. 여기 데모 및 코드를 찾기 : codepen.io/Grienauer/pen/Grogdx
Grienauer에게

@Grienauer 나는 똑같은 일을했고, 이미 그것을 공유했다는 것을 깨닫지 못했습니다! 내 유일한 차이점은 내가 흰색의 배경 색상 기본값이다
tehlivi을

7

Phrogzephemer 의 훌륭한 답변 덕분에 여기 에 가장 적합한 RGBA 색상 을 자동으로 계산 하는 SASS 함수가 있습니다.

원하는 색상과 기존 배경으로 호출하면 반올림 오류로 인해 각 RGB 구성 요소의 ± 1 / 256 이내에서 원하는 결과를 제공하는 최적 (가장 투명 함을 의미)에 해당하는 RGBA 색상을 계산합니다.

@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);
}

방금 여러 조합 (모든 Bootswatch 테마)에 대해 테스트 한 결과 dark-on-light 및 light-on-dark 결과 모두에서 효과가 있습니다.

추신 : 결과 색상에서 ± 1 / 256 이상의 정밀도가 필요한 경우 rgba 색상을 혼합 할 때 어떤 종류의 반올림 알고리즘 브라우저가 적용되는지 알고 있어야합니다 (표준화되었는지 여부는 모르겠습니다). 조건을 기존 @while에 추가 $alpha하여 원하는 정밀도에 도달 할 때까지 계속 증가 합니다.


2
참고로,이 함수는 Stylus에 다음과 같이 존재합니다 transparentify(). stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ... 이것을 Stylus에 수동으로 이식 한 후 발견 한 ...
weotch

6

@Phrogz의 대답에서 :

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

그래서:

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

그래서:

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

당신의 모든 값을 선택할 수 있습니다 a1, 이것은의 해당 값을 찾을 수 있습니다 r1, g1그리고 b1필요합니다. 예를 들어 알파 1을 선택하면 RGB1 = RGB3이 필요하지만 알파 0을 선택하면 솔루션이 제공되지 않습니다 (분명히).


1

지금까지 찾은 가장 실용적인 솔루션은 색상 선택 도구로 결과 색상을 측정 한 다음 측정 된 색상을 오버레이에 사용하는 것입니다. 이 방법은 완벽한 색상 일치를 제공합니다.

다른 믹스 인을 사용해 보았지만 반올림 오류로 인해 육안으로도 차이를 볼 수있었습니다


1
OP는 아마도 동적으로 결정을 내리는 방법을 원했지만 구체적으로 언급되지 않았으며 귀하의 답변은 정적 색상 / 알파 선택에 대한 좋은 해킹을 제공합니다.
Erik Knowles

0

@Tobia의 답변을 확장하고 transparentify와 더 비슷하게 불투명도를 지정하려면 다음을 수행하십시오.

@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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.