다음은 프로그래밍 방식으로 16 진수 색상을 특정 양만큼 밝게 또는 어둡게하기 위해 작업 한 기능입니다. 밝게 또는 어둡게 할 양에 대해 "3F6D2A"
색상 ( col
) 및 base10 정수 ( amt
) 와 같은 문자열을 전달하십시오 . 어둡게하려면 음수 (예 :)를 입력 -20
하십시오.
내가 이것을 한 이유는 내가 찾은 모든 솔루션 덕분에 지금까지는 문제를 지나치게 복잡하게 만드는 것처럼 보였습니다. 그리고 나는 단지 몇 줄의 코드로 할 수 있다고 생각했습니다. 문제가 발견되면 속도를 높이도록 조정하십시오.
function LightenDarkenColor(col, amt) {
col = parseInt(col, 16);
return (((col & 0x0000FF) + amt) | ((((col >> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16)).toString(16);
}
// TEST
console.log( LightenDarkenColor("3F6D2A",40) );
개발 용으로 여기에 읽기 쉬운 버전이 있습니다.
function LightenDarkenColor(col, amt) {
var num = parseInt(col, 16);
var r = (num >> 16) + amt;
var b = ((num >> 8) & 0x00FF) + amt;
var g = (num & 0x0000FF) + amt;
var newColor = g | (b << 8) | (r << 16);
return newColor.toString(16);
}
// TEST
console.log(LightenDarkenColor("3F6D2A", -40));
마지막으로 처음에 “#”가 있거나 없을 수있는 색상을 처리하는 버전입니다. 부적절한 색상 값 조정
function LightenDarkenColor(col,amt) {
var usePound = false;
if ( col[0] == "#" ) {
col = col.slice(1);
usePound = true;
}
var num = parseInt(col,16);
var r = (num >> 16) + amt;
if ( r > 255 ) r = 255;
else if (r < 0) r = 0;
var b = ((num >> 8) & 0x00FF) + amt;
if ( b > 255 ) b = 255;
else if (b < 0) b = 0;
var g = (num & 0x0000FF) + amt;
if ( g > 255 ) g = 255;
else if ( g < 0 ) g = 0;
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}
이제 두 줄만있는 것이 아니라 훨씬 더 단순 해 보이며 “#”을 사용하지 않고 범위를 벗어난 색상을 확인할 필요가 없으면 몇 줄 밖에되지 않습니다.
“#”을 사용하지 않으면 다음과 같은 코드로 추가 할 수 있습니다.
var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);
내 주요 질문은 여기에 맞습니까? 이것이 일부 (정상적인) 상황을 포함하지 않습니까?
답변
글쎄,이 대답은 그 자신의 짐승이되었습니다. 많은 새로운 버전, 어리석은 짓이 길어졌습니다. 이 답변에 많은 기여를 해주신 모든 분들께 감사드립니다. 그러나 대중을 위해 단순하게 유지하기 위해. 이 답변의 진화에 대한 모든 버전 / 역사를 내 github에 보관했습니다 . 그리고 최신 버전으로 여기에서 StackOverflow를 깨끗하게 시작했습니다. 이 버전에 대해 Mike ‘Pomax’Kamermans 에게 특별한 감사를드립니다 . 그는 나에게 새로운 수학을 주었다.
이 기능 ( pSBC
)은 16 진수 또는 RGB 웹 색상을 사용합니다. pSBC
어둡거나 밝게 음영 처리하거나 두 번째 색상과 혼합하고 오른쪽을 통해 전달할 수도 있지만 16 진수에서 RGB (Hex2RGB) 또는 RGB에서 16 진수 (RGB2Hex)로 변환 할 수도 있습니다. 어떤 색상 형식을 사용하고 있는지조차 모릅니다.
특히 많은 기능을 고려할 때 가장 빠르며 아마도 가장 빠릅니다. 제작에 오랜 시간이 걸렸습니다. 내 github 의 전체 이야기를 참조하십시오 . 가장 작고 빠른 음영 처리 또는 혼합 방법을 원하면 아래의 마이크로 기능을 참조하여 2 라이너 속도 악마 중 하나를 사용하십시오. 강렬한 애니메이션에는 훌륭하지만이 버전은 대부분의 애니메이션에 충분히 빠릅니다.
이 기능은 로그 블렌딩 또는 선형 블렌딩을 사용합니다. 그러나 색상을 올바르게 밝게하거나 어둡게하기 위해 HSL로 변환되지 않습니다. 따라서이 기능의 결과는 HSL을 사용하는 훨씬 크고 느린 기능과 다릅니다 .
풍모:
- 문자열 형태의 표준 16 진수 색상을 자동 감지하고 받아들입니다. 예를 들면 다음
"#AA6622"
과 같습니다. 또는"#bb551144"
. - 문자열 형태의 표준 RGB 색상을 자동 감지하고 수용합니다. 예를 들면 다음
"rgb(123,45,76)"
과 같습니다. 또는"rgba(45,15,74,0.45)"
. - 백분율로 색상을 흰색 또는 검은 색으로 음영 처리합니다.
- 백분율로 색상을 혼합합니다.
- Hex2RGB와 RGB2Hex 변환을 동시에 수행하거나 단독으로 수행합니다.
- #RGB (또는 #RGBA) 형식으로 3 자리 (또는 4 자리 (알파 포함) HEX) 색상 코드를 사용할 수 있습니다. 그것들을 확장시킬 것입니다. 예를 들면 다음과 같습니다
"#C41"
된다"#CC4411"
. - 알파 채널을 수락하고 (선형) 혼합합니다. 중 하나 경우
c0
(에서) 색상 또는c1
(을) 색상은 알파 채널을 가지고, 다음 반환 된 색상은 알파 채널을해야합니다. 두 색상에 모두 알파 채널이있는 경우 반환 된 색상은 주어진 비율 (일반 색상 채널 인 것처럼)을 사용하여 두 알파 채널의 선형 혼합입니다. 두 색상 중 하나에 만 알파 채널이있는 경우이 알파는 반환 된 색상으로 전달됩니다. 이를 통해 투명도 수준을 유지하면서 투명 색상을 혼합 / 음영 할 수 있습니다. 또는 투명도 수준도 혼합해야하는 경우 두 색상에 모두 알파가 있는지 확인하십시오. 음영 처리시 알파 채널을 통해 직선으로 전달됩니다. 당신은 또한 알파 채널을 음영 기본 음영을 원한다면, 사용rgb(0,0,0,1)
또는rgb(255,255,255,1)
같은c1
(to) 색상 (또는 해당하는 16 진수). RGB 색상의 경우 반환 된 색상의 알파 채널은 소수점 이하 3 자리로 반올림됩니다. - 블렌딩을 사용할 때 RGB2Hex 및 Hex2RGB 변환은 암시 적입니다.
c0
(from) 색상에 관계없이 ; 반환 된 색상은 항상c1
(to) 색상 의 색상 형식입니다 (있는 경우). 어떤이없는 경우c1
(에) 색상, 다음 통과'c'
는 AS의c1
색상과 그늘과 어떤 변환됩니다c0
색상입니다. 변환 만 필요한 경우0
백분율 (p
) 로도 전달 하십시오 . 경우c1
색상이 생략 또는 비가string
전달되고,이 변환하지 않습니다. - 보조 기능도 전역에 추가됩니다.
pSBCr
16 진수 또는 RGB 색상을 전달할 수 있으며이 색상 정보가 포함 된 객체를 반환합니다. {r : XXX, g : XXX, b : XXX, a : X.XXX} 형식입니다. 여기서.r
,.g
및.b
범위는 0 ~ 255입니다. 알파가없는 경우 :.a
-1입니다. 그렇지 않은 경우 :.a
범위는 0.000 ~ 1.000입니다. - RGB 출력의 경우 알파 채널이있는 색상이 (시작) 및 / 또는 (
rgba()
끝)rgb()
으로 전달되면 출력 됩니다 .c0
c1
- 사소한 오류 검사가 추가되었습니다. 완벽하지 않습니다. 여전히 충돌하거나 혼란 스러울 수 있습니다. 그러나 그것은 약간의 물건을 잡을 것입니다. 기본적으로 구조가 어떤 방식으로 잘못되었거나 백분율이 숫자가 아니거나 범위를 벗어나면을 반환
null
합니다. 예를 들어pSBC(0.5,"salt") == null
,#salt
올바른 색상 이라고 생각 합니다.return null;
이 기능을 제거하기 위해 끝나는 네 줄을 삭제하고 더 빠르고 작게 만드십시오. - 로그 블렌딩을 사용합니다. 패스
true
에 대한의l
선형 혼합을 사용 (4 매개 변수).
암호:
// Version 4.0
const pSBC=(p,c0,c1,l)=>{
let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
if(!this.pSBCr)this.pSBCr=(d)=>{
let n=d.length,x={};
if(n>9){
[r,g,b,a]=d=d.split(","),n=d.length;
if(n<3||n>4)return null;
x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
}else{
if(n==8||n==6||n<4)return null;
if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
d=i(d.slice(1),16);
if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
}return x};
h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
if(!f||!t)return null;
if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
}
용법:
// Setup:
let color1 = "rgb(20,60,200)";
let color2 = "rgba(20,60,200,0.67423)";
let color3 = "#67DAF0";
let color4 = "#5567DAF0";
let color5 = "#F3A";
let color6 = "#F3A9";
let color7 = "rgb(200,60,20)";
let color8 = "rgba(200,60,20,0.98631)";
// Tests:
/*** Log Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(166,171,225)
pSBC ( -0.4, color5 ); // #F3A + [40% Darker] => #c62884
pSBC ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(225,171,166,0.98631)
// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #a6abe1ac
// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)
// Blending
pSBC ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(142,60,142,0.83)
pSBC ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(168,60,111,0.67423)
pSBC ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(134,191,208)
pSBC ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #86bfd0
/*** Linear Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1, false, true ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
pSBC ( -0.4, color5, false, true ); // #F3A + [40% Darker] => #991f66
pSBC ( 0.42, color8, false, true ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)
// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c", true ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac
// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c", true ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)
// Blending
pSBC ( -0.5, color2, color8, true ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.83)
pSBC ( 0.7, color2, color7, true ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
pSBC ( 0.25, color3, color7, true ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
pSBC ( 0.75, color7, color3, true ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9
/*** Other Stuff ***/
// Error Checking
pSBC ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null (Invalid Input Color)
pSBC ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null (Invalid Percentage Range)
pSBC ( 0.42, {} ); // [object Object] + [42% Lighter] => null (Strings Only for Color)
pSBC ( "42", color1 ); // rgb(20,60,200) + ["42"] => null (Numbers Only for Percentage)
pSBC ( 0.42, "salt" ); // salt + [42% Lighter] => null (A Little Salt is No Good...)
// Error Check Fails (Some Errors are not Caught)
pSBC ( 0.42, "#salt" ); // #salt + [42% Lighter] => #a5a5a500 (...and a Pound of Salt is Jibberish)
// Ripping
pSBCr ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'r':85,'g':103,'b':218,'a':0.941}
아래 그림은 두 가지 혼합 방법의 차이점을 보여줍니다.
마이크로 기능
속도와 크기를 정말로 원한다면 16 진수가 아닌 RGB를 사용해야합니다. RGB는 더 간단하고 간단합니다. HEX는 쓰기 속도가 너무 느리고 간단한 두 줄짜리 (IE, 3, 4, 6 또는 8 자리 HEX 코드 일 수 있음)에 비해 너무 많은 맛이 있습니다. 또한 일부 기능, 오류 검사, HEX2RGB 또는 RGB2HEX를 희생해야합니다. 또한 색상 혼합 수학 및 음영 또는 혼합을 원하는 경우 특정 기능 (아래의 기능 이름을 기준으로)을 선택해야합니다. 이 기능은 알파 채널을 지원합니다. 두 입력 색상에 모두 알파가 있으면 선형 혼합됩니다. 두 색상 중 하나에 만 알파가있는 경우 결과 색상으로 그대로 전달됩니다. 다음은 매우 빠르고 작은 두 가지 라이너 기능입니다.
const RGB_Linear_Blend=(p,c0,c1)=>{
var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+j;
}
const RGB_Linear_Shade=(p,c)=>{
var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:255*p,P=P?1+p:1-p;
return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
}
const RGB_Log_Blend=(p,c0,c1)=>{
var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+j;
}
const RGB_Log_Shade=(p,c)=>{
var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:p*255**2,P=P?1+p:1-p;
return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
}
더 많은 정보를 원하십니까? github 에서 전체 쓰기를 읽으십시오 .
PT
(Ps 다른 블렌딩 방법에 대한 수학이 있다면 공유하십시오.)
답변
나는 나를 위해 아주 좋은 해결책을 만들었습니다.
function shadeColor(color, percent) {
var R = parseInt(color.substring(1,3),16);
var G = parseInt(color.substring(3,5),16);
var B = parseInt(color.substring(5,7),16);
R = parseInt(R * (100 + percent) / 100);
G = parseInt(G * (100 + percent) / 100);
B = parseInt(B * (100 + percent) / 100);
R = (R<255)?R:255;
G = (G<255)?G:255;
B = (B<255)?B:255;
var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));
return "#"+RR+GG+BB;
}
예를 들어 밝게 :
shadeColor("#63C6FF",40);
어둡게하는 예 :
shadeColor("#63C6FF",-40);
답변
여기에 Eric의 답변을 바탕으로 한 매우 간단한 라이너가 있습니다.
function adjust(color, amount) {
return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}
예 :
adjust('#ffffff', -20) => "#ebebeb"
adjust('000000', 20) => "#141414"
답변
이것이 내가 당신의 기능에 따라 사용한 것입니다. 나는 더 직관적이기 때문에 백분율보다 단계를 사용하는 것을 선호합니다.
예를 들어 200 파랑 값의 20 %는 40 파랑 값의 20 %와 크게 다릅니다.
어쨌든, 원래 기능에 감사드립니다.
function adjustBrightness(col, amt) {
var usePound = false;
if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}
var R = parseInt(col.substring(0,2),16);
var G = parseInt(col.substring(2,4),16);
var B = parseInt(col.substring(4,6),16);
// to make the colour less bright than the input
// change the following three "+" symbols to "-"
R = R + amt;
G = G + amt;
B = B + amt;
if (R > 255) R = 255;
else if (R < 0) R = 0;
if (G > 255) G = 255;
else if (G < 0) G = 0;
if (B > 255) B = 255;
else if (B < 0) B = 0;
var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));
return (usePound?"#":"") + RR + GG + BB;
}
답변
함수를 시도했는데 약간의 버그가 있습니다. 예를 들어 일부 최종 ‘r’값이 1 자리이면 결과는 다음과 같이 나타납니다. 예를 들어 올바른 값이 ‘0a0a0a’인 경우 ‘a0a0a’입니다. 방금 반환 대신 다음을 추가하여 방금 수정했습니다.
var rStr = (r.toString(16).length < 2)?'0'+r.toString(16):r.toString(16);
var gStr = (g.toString(16).length < 2)?'0'+g.toString(16):g.toString(16);
var bStr = (b.toString(16).length < 2)?'0'+b.toString(16):b.toString(16);
return (usePound?"#":"") + rStr + gStr + bStr;
어쩌면 그렇게 좋지는 않지만 일을합니다. 훌륭한 기능, BTW. 내가 필요한 것만 🙂
답변
RGB> hsl 변환에 대해 생각해 보셨습니까? 광도를 위아래로 움직입니까? 그것이 내가 갈 길입니다.
일부 알고리즘을 간략히 살펴보면 다음 사이트를 얻었습니다.
PHP :
http://serennu.com/colour/rgbtohsl.php
위 링크를 수정 하면 더 이상 유효하지 않습니다. 페이지 소스 또는 요지에 대한 자식 허브를 볼 수 있습니다
또는 다른 StackOverflow 질문 을 살펴 보는 것이 좋습니다.
이것이 OP에 대한 올바른 선택은 아니지만 다음은 원래 제안했던 코드의 근사치입니다. (rgb / hsl 변환 기능이 있다고 가정)
var SHADE_SHIFT_AMOUNT = 0.1;
function lightenShade(colorValue)
{
if(colorValue && colorValue.length >= 6)
{
var redValue = parseInt(colorValue.slice(-6,-4), 16);
var greenValue = parseInt(colorValue.slice(-4,-2), 16);
var blueValue = parseInt(colorValue.slice(-2), 16);
var hsl = rgbToHsl(redValue, greenValue, blueValue);
hsl[2]= Math.min(hsl[2] + SHADE_SHIFT_AMOUNT, 1);
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
}
return null;
}
function darkenShade(colorValue)
{
if(colorValue && colorValue.length >= 6)
{
var redValue = parseInt(colorValue.slice(-6,-4), 16);
var greenValue = parseInt(colorValue.slice(-4,-2), 16);
var blueValue = parseInt(colorValue.slice(-2), 16);
var hsl = rgbToHsl(redValue, greenValue, blueValue);
hsl[2]= Math.max(hsl[2] - SHADE_SHIFT_AMOUNT, 0);
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
}
return null;
}
이것은 다음을 가정합니다.
- 당신은 기능을 가지고
hslToRgb
와rgbToHsl
. - 매개 변수
colorValue
는 #RRGGBB 형식의 문자열입니다.
CSS를 논의하고 있지만 IE9 / Chrome / Firefox에 hsl / hsla 를 지정하는 구문이 있습니다.
답변
C # 버전 … # FF12AE34 형식의 색상 문자열이 표시되며 #FF를 잘라 내야합니다.
private string GetSmartShadeColorByBase(string s, float percent)
{
if (string.IsNullOrEmpty(s))
return "";
var r = s.Substring(3, 2);
int rInt = int.Parse(r, NumberStyles.HexNumber);
var g = s.Substring(5, 2);
int gInt = int.Parse(g, NumberStyles.HexNumber);
var b = s.Substring(7, 2);
int bInt = int.Parse(b, NumberStyles.HexNumber);
var t = percent < 0 ? 0 : 255;
var p = percent < 0 ? percent*-1 : percent;
int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);
return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
}