흰색 위에 RGB를 RGBA로 변환
예를 들어 #F4F8FB
(또는 rgb(244, 248, 251)
) 와 같은 16 진수 색상을 투명으로 가능한 rgba 색상 (흰색 위에 표시 할 때) 으로 변환하려고 합니다. 말이 되나요? 알고리즘을 찾고 있거나 적어도 그렇게하는 방법에 대한 알고리즘을 찾고 있습니다.
예를 들어 :
rgb( 128, 128, 255 ) --> rgba( 0, 0, 255, .5 )
rgb( 152, 177, 202 ) --> rgba( 50, 100, 150, .5 ) // can be better(lower alpha)
아이디어?
Guffa의 답변을 기반으로 한 FYI 솔루션 :
function RGBtoRGBA(r, g, b){
if((g == null) && (typeof r === 'string')){
var hex = r.replace(/^\s*#|\s*$/g, '');
if(hex.length === 3){
hex = hex.replace(/(.)/g, '$1$1');
}
r = parseInt(hex.substr(0, 2), 16);
g = parseInt(hex.substr(2, 2), 16);
b = parseInt(hex.substr(4, 2), 16);
}
var min, a = (255 - (min = Math.min(r, g, b))) / 255;
return {
r : r = 0|(r - min) / a,
g : g = 0|(g - min) / a,
b : b = 0|(b - min) / a,
a : a = (0|1000*a)/1000,
rgba : 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')'
};
}
RGBtoRGBA(204, 153, 102) == RGBtoRGBA('#CC9966') == RGBtoRGBA('C96') ==
{
r : 170,
g : 85 ,
b : 0 ,
a : 0.6,
rgba : 'rgba(170, 85, 0, 0.6)'
}
가장 낮은 색 구성 요소를 사용하여 알파 값으로 변환하십시오. 그런 다음 가장 낮은 값을 빼고 알파 값으로 나누어 색상 구성 요소의 크기를 조정합니다.
예:
152 converts to an alpha value of (255 - 152) / 255 ~ 0.404
152 scales using (152 - 152) / 0.404 = 0
177 scales using (177 - 152) / 0.404 ~ 62
202 scales using (202 - 152) / 0.404 ~ 123
따라서로 rgb(152, 177, 202)
표시됩니다 rgba(0, 62, 123, .404)
.
Photoshop에서 색상이 실제로 완벽하게 일치하는지 확인했습니다.
r, g 및 b를 입력 값으로, r ', g', b '및 a'를 출력 값으로, 모두 1과 0 사이에서 (수학을 더 예쁘게 만들 때) 스케일링합니다. 색상을 오버레이하는 공식 :
r = a' * r' + 1 - a'
g = a' * g' + 1 - a'
b = a' * b' + 1 - a'
1-a '항은 배경 기여도를 나타내고 다른 항은 전경을 나타냅니다. 대수를 수행하십시오.
r = a' * (r' - 1) + 1
r - 1 = a' * (r' - 1)
(r - 1) / (r' - 1) = a'
(r' - 1) / (r - 1) = 1 / a'
r' - 1 = (r - 1) / a'
r' = (r - 1) / a' + 1
직관적으로, 최소 색상 값이 문제의 제한 요소가 될 것이므로 이것을 m에 바인딩하십시오.
m = min(r, g, b)
투명도를 최대화하려면 해당 출력 값 m '을 0으로 설정하십시오.
0 = (m - 1) / a' + 1
-1 = (m - 1) / a'
-a' = m - 1
a' = 1 - m
따라서 자바 스크립트에서 (길을 따라 1에서 255로 번역) :
function rgba(r, g, b) {
var a = 1 - Math.min(r, Math.min(g, b)) / 255;
return [255 + (r - 255) / a, 255 + (g - 255) / a, 255 + (b - 255) / a, a];
}
Note that I'm assuming that a' is opacity here. It is trivial to change it to transparency - just remove the "1 -" from the formula for a'. Anothing thing to note is that this does not seem to produce exact results - it said that the opacity was 0.498 for the example you gave above (128, 128, 255). However, this is extremely close.
I'd look to RGB<->HSL conversion. I.e. luminosity == amount of white == amount of transparency.
For your example rgb( 128, 128, 255 )
, we need to shift RGB values to 0
first by maximum amount, i.e. to rgb( 0, 0, 128 )
- that would be our color with as few of white as possible. And after that, using formula for luminance, we calculate amount of white we need to add to our dark color to get original color - that would be our alpha:
L = (MAX(R,G,B) + MIN(R,G,B))/2
L1 = (255 + 128) / 2 = 191.5
L2 = (128 + 0) /2 = 64
A = (191,5 - 64) / 255 = 0,5;
Hope that makes sense. :)
For those of you using SASS/SCSS, I've wrote a small SCSS function so you can easily use the algorithm described by @Guffa
@function transparentize-on-white($color)
{
$red: red($color);
$green: green($color);
$blue: blue($color);
$lowestColorComponent: min($red, $green, $blue);
$alpha: (255 - $lowestColorComponent) / 255;
@return rgba(
($red - $lowestColorComponent) / $alpha,
($green - $lowestColorComponent) / $alpha,
($blue - $lowestColorComponent) / $alpha,
$alpha
);
}
I'm just describing an idea for the algorithm, no full solution:
Basically, you have three numbers x
, y
, z
and you are looking for three new numbers x'
, y'
, z'
and a multiplier a
in the range [0,1] such that:
x = a + (1 - a) x'
y = a + (1 - a) y'
z = a + (1 - a) z'
This is written in units where the channels also take values in the range [0,1]. In 8bit discrete values, it'd be something like this:
x = 255 a + (1 - a) x'
y = 255 a + (1 - a) y'
z = 255 a + (1 - a) z'
Moreover, you want the largest possible value a
. You can solve:
a = (x - x')/(255 - x') x' = (x - 255 a)/(1 - a)
Etc. In real values this has infinitely many solutions, just plug in any real number a
, but the problem is to find a number for which the discretization error is minimal.
This should do it:
let x = min(r,g,b)
a = 1 - x/255 # Correction 1
r,g,b = ( (r,g,b) - x ) / a # Correction 2
The top answer didn't work for me with low color components. For example it does not calculate correct alpha if color is #80000. Technically it should make it into #ff0000 with alpha 0.5. To resolve this, you need to use RGB -> HSL -> RGBA conversion. This is pseudo code to get the correct values:
//Convert RGB to HSL
hsl = new HSL(rgb)
//Use lightness as alpha
alpha = hsl.Lightness
//For #80000 lightness is 0.5, so we have to take this into account.
//Lightness more than 0.5 converts to alpha 1 and below is a linear ratio
if (alpha > 0.5)
{
alpha = 1;
}
else
{
alpha = alpha / 0.5;
//We need to drop the lightness of the color to 0.5 to get the actual color
//that needs to display. Alpha blending will take care of that.
hsl.Lightness = 0.5;
}
newRgb = hsl.convertToRgb()
"newRgb" will contain the value of the new adjusted color and use "alpha" variable to control the transparency.
참고URL : https://stackoverflow.com/questions/6672374/convert-rgb-to-rgba-over-white
'Programming' 카테고리의 다른 글
Vim을 Java IDE로 사용하기위한 팁? (0) | 2020.05.11 |
---|---|
차이점 (0) | 2020.05.11 |
장고 :“프로젝트”대“앱” (0) | 2020.05.11 |
Logcat에서 안무가 메시지의 의미 (0) | 2020.05.11 |
기존 스키마에서 테이블 관계 다이어그램 생성 (SQL Server) (0) | 2020.05.11 |