RGBA 스타일 색상을 캔버스 친화적 인 색상으로 변환하는 방법은 무엇입니까?

SuperUberDuper

계산 된 스타일과 같은 색으로 캔버스에 그리려고합니다.

같은 색상의 경우 괜찮습니다.

rgb (0, 255, 255) "

그러나 같은 것을 위해

rgba (0, 0, 0, 0)

캔버스에서는 검은 색이지만 브라우저에서는 흰색입니다.

블라인드 맨 67

일치하는 DOM 색상 혼합

빨강, 녹색, 파랑 및 알파 채널

대부분의 경우 브라우저에 표시되는 모든 그래픽은 4 개의 채널로 구성됩니다. 처음 3 개는 색상 채널이며 각 구성 요소 색상, 빨간색, 녹색 및 파란색의 강도를 나타냅니다. 네 번째 채널은 알파 채널이며 픽셀의 투명도를 나타냅니다. 메모리에 저장된 각 채널은 8 비트 폭으로 256 개의 개별 값을 허용합니다. 색상 채널의 경우 0은 기여하지 않음을 나타내며 255는 최대 강도를 나타냅니다. 알파 채널에는 완전 투명 0부터 완전 불투명 255까지 가능한 256 개의 값이 있습니다. 그러나 알파는 0에서 1까지의 단위 값으로 표시되는 것이 일반적입니다.

CSS 색상 문자열 rgba(red,green,blue,alpha)사용하여 픽셀 색상을 나타낼 수 있습니다 .

소스 오버 블렌딩

픽셀의 알파 값이 1 미만 (바이트 값 <255)이면 그 아래에있는 픽셀과 혼합되고 (이 작업은 하드웨어에서 수행됨) 화면의 결과 픽셀은 두 픽셀의 혼합입니다.

픽셀 혼합을위한 표준 공식은 1984 년 Porter-Duff 합성 논문을 기반으로합니다.

가장 간단한 형식으로 한 픽셀을 다른 픽셀 위에 그릴 때 모든 채널에 대한 바이트 값을 사용하는 다음 절차가 사용되며 '소스 오버'라고합니다. ref W3C 단순 알파 합성

// the destination is the pixel being drawn over
var destination = {r : 255, g : 0, b : 0, a : 255}; // red opaque 
// source is the pixel being put on top
var source = {r : 0, g : 255, b : 0, a : 127}; // green about half transparent

// normalised means brought to a unit value ranging between 0-1 inclusive
var ad = destination.a / 255; // normalise the destination alpha
var as = source.a / 255;      // and source

// get the normalised alpha value for the resulting pixel
var ar = as + ad * (1  - as);


// the resulting pixel
var result = {};
// calculate the colour channels.
result.r = (source.r * as  + destination.r * ad * (1 - as)) / ar;
result.g = (source.g * as  + destination.g * ad * (1 - as)) / ar;
result.b = (source.b * as  + destination.b * ad * (1 - as)) / ar;

// calculate the alpha channel
result.a = ar * 255; // bring alpha back to the byte value
                     // Though it may seem silly to convert to 8 bit range
                     // it is important to do so because there is a 
                     // considerable loss of precision in all these 
                     // calculations

// convert to a pixel value a used in 2D context getImageData
var pixel = new Uint8ClampedArray([
    result.r,
    result.g,
    result.b,
    result.a,
]);

같은 일을 할 함수에 두 개의 도우미 함수를 넣으십시오.

function blendSourceOver(s,d){
    var ad = d.a / 255; // normalise the destination alpha
    var as = s.a / 255;      // and source
    var ar = as + ad * (1  - as);
    var r = {};
    r.r = Math.round((s.r * as  + d.r * ad * (1 - as)) / ar);
    r.g = Math.round((s.g * as  + d.g * ad * (1 - as)) / ar);
    r.b = Math.round((s.b * as  + d.b * ad * (1 - as)) / ar);
    r.a = Math.round(ar * 255); 
    return r;
}
function rgbaToColour(col){
    col = col.replace("rgba(","").replace(")","").split(",");
    var r = {};
    r.r = Number(col[0]);
    r.g = Number(col[1]);
    r.b = Number(col[2]);
    r.a = Math.round(Number(col[3]) * 255);
    return r;
}

function colourTorgba(col){
    return `rgba(${col.r},${col.g},${col.b},${col.a / 255})`;
}

캔버스에서 일치하는 DOM 결과.

문제는 캔버스가 DOM과 일치하도록하는 것입니다. 두 가지 요소를 하나씩 고려해 보겠습니다. 첫 번째 div는 빨간색이고 두 번째 div는 알파가 0.5 인 파란색입니다.

DOM 색상 혼합 예

.exm {  width : 100px; height: 30px; color: white; text-align: center;} 
 <div style = "background : rgba(255, 0, 0, 1);" class = "exm">
     <div style = "background : rgba(0, 0, 255, 0.5); position : relative; top : 0px; left : 0px;"  class = "exm">
          Red + Blue
     </div>
 </div>

결과 색상은 무엇입니까?

이제 결과 색상을 캔버스에 렌더링하고 싶다고 가정합니다. 내가 아는 한 색상을 샘플링하는 직접적인 방법이 없으므로 알려진 색상으로 만들어야합니다.

이를 수행 할 수있는 두 가지 방법이 있습니다.

렌더 복제로

첫 번째는 DOM에서 일어나는 일을 복제하는 것입니다. 빨간색을 추가 한 다음 그 위에 파란색을 그립니다.

렌더링 단계를 복제하여 DOM 색상을 일치시키는 예

var ctx = can.getContext("2d");
ctx.fillStyle = "rgba(255, 0, 0, 1)";
ctx.fillRect(0, 0, 100, 30);
ctx.fillStyle = "rgba(0, 0, 255, 0.5)";
ctx.fillRect(0, 0, 100, 30);
ctx.font = "18px arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("Canvas", 50, 22);
var dat = ctx.getImageData(1,1,1,1).data;
colResult.textContent = `Resulting colour rgba(${dat[0]},${dat[1]},${dat[2]},${dat[3]/255})`;
.exm {  width : 100px; height: 30px; color: white; text-align: center; font : 18px arial;} 
.text {color : black; font-size: xx-small;}
 <p class="exm text"> Match DOM and Canvas colours via rendering replication</p>

 <div style = "background : rgba(255, 0, 0, 1);"  class = "exm">
     <div style = "background : rgba(0, 0, 255, 0.5); position : relative; top : 0px; left : 0px;" class = "exm"> DOM 
     </div>
 </div>
 <canvas id = "can" width = "100" height = "30"  class = "exm"></canvas>
 <p class="exm text" id="colResult"></p>

계산으로

두 번째는 소스 오버 블렌드 기능을 사용하여 색상을 계산하는 것입니다.

Porter-Duff "source-over"블렌딩 을 사용하여 색상을 계산하는 예 .

function blendSourceOver(s,d){
    var ad = d.a / 255; // normalise the destination alpha
    var as = s.a / 255;      // and source
    var ar = as + ad * (1  - as);
    var r = {};
    r.r = Math.round((s.r * as  + d.r * ad * (1 - as)) / ar);
    r.g = Math.round((s.g * as  + d.g * ad * (1 - as)) / ar);
    r.b = Math.round((s.b * as  + d.b * ad * (1 - as)) / ar);
    r.a = Math.round(ar * 255); 
    return r;
}
function rgbaToColour(col){
    col = col.replace("rgba(","").replace(")","").split(",");
    var r = {};
    r.r = Number(col[0]);
    r.g = Number(col[1]);
    r.b = Number(col[2]);
    r.a = Math.round(Number(col[3]) * 255);
    return r;
}

function colourTorgba(col){
    return `rgba(${col.r},${col.g},${col.b},${col.a / 255})`;
}


var  colour = colourTorgba(
                  blendSourceOver(
                      rgbaToColour("rgba(0, 0, 255, 0.5)"), // source
                      rgbaToColour("rgba(255, 0, 0, 1)") // destination
                  )
               );

 
var ctx = can.getContext("2d");
ctx.fillStyle = colour;
ctx.fillRect(0, 0, 100, 30);
ctx.font = "18px arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("Canvas", 50, 22);
colResult.textContent = "Resulting colour "+colour;
.exm {  width : 100px; height: 30px; color: white; text-align: center; font : 18px arial;} 
.text {color : black; font-size: xx-small;}
 <p class="exm text"> Match DOM and Canvas colours by calculation</p>
 <div style = "background : rgba(255, 0, 0, 1);"  class = "exm">
     <div style = "background : rgba(0, 0, 255, 0.5); position : relative; top : 0px; left : 0px;" class = "exm"> DOM 
     </div>
 </div>
 <canvas id = "can" width = "100" height = "30"  class = "exm"></canvas>
 <p class="exm text" id="colResult"></p>

알파 = 1 확인

이제 모든 계산을 수행 할 때 항상 알파 값이 1 인 색상으로 끝나야하므로주의해야합니다. 그렇지 않은 경우 일부 정보가 누락 된 것입니다. 모든 DOM 색상 블렌딩의 최종 결과는 Alpha = 1 (배경)이며, 추가 투명도는 DOM의 컨텍스트를 벗어나 브라우저 창의 일부입니다.

계산 순서

두 개 이상의 색상을 계산하려면 DOM에서 수행 한 것과 동일한 순서로 계산해야합니다. 주문이 잘못된 경우 결과 색상도 올바르지 않습니다.

예를 들어 빨간색 배경이 있고 0.5 알파가있는 파란색 div가 있고 그 위에 0.5 알파가있는 녹색 div가 있다고 가정합니다. 계산 순서는 상향식입니다.

background = rgbaToColour("rgba(255,0,0,1)");
div1 = rgbaToColour("rgba(0,0,255,0.5)");
div2 = rgbaToColour("rgba(0,255,0,0.5)");

먼저 배경과 div1의 결과를 div2와 혼합합니다.

var temp = blendSourceOver(div1,background);   // source then destination
var result = blendSourceOver(div2,temp);    // source then temp destination
console.log(colourTorgb(result)); // => "rgba(63,128,64,1)"

다른 방법으로하면 완전히 다른 색상이됩니다.

var temp = blendSourceOver(div1,background);   // source then destination
var result = blendSourceOver(div1,temp);    // source then temp destination
console.log(colourTorgb(result)); // => "rgba(63,64,128,1)"

추가 읽기

W3C (서스펜스 충전) 합성 및 블렌딩 레벨 2 에 대해 알아야 할 모든 내용 은이 주제를보다 자세하게 다룹니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Android에서 캔버스의 색상을 5 초마다 동적으로 변경하는 방법은 무엇입니까?

분류에서Dev

Tkinter 캔버스에서 닫힌 폴리 라인의 색상을 지정하는 방법은 무엇입니까?

분류에서Dev

색맹 친화적 인 30 가지 고유 한 색상을 생성하는 방법은 무엇입니까?

분류에서Dev

바닐라 자바 스크립트를 사용하여 인라인 SVG의 색상을 동적으로 변경하는 방법은 무엇입니까?

분류에서Dev

대화 상자에서 캔버스를 인스턴스화하는 방법은 무엇입니까?

분류에서Dev

jQuery Mobile에서 링크 텍스트 색상을 동적으로 변경하는 방법은 무엇입니까?

분류에서Dev

동적으로 생성 된 값의 텍스트 색상을 변경하는 방법은 무엇입니까? -PHP

분류에서Dev

Google 차트 캔들 스틱으로 세로선의 색상을 변경하는 방법은 무엇입니까?

분류에서Dev

jquery에서 인라인 스타일 테두리 색상을 얻는 방법은 무엇입니까?

분류에서Dev

NSAttributedString (ios)에서 밑줄 스타일에 색상을 적용하는 방법은 무엇입니까?

분류에서Dev

픽셀 색상을 기반으로 RGB 이미지의 부울 마스크를 생성하는 가장 비단뱀적인 방법은 무엇입니까?

분류에서Dev

부트 스트랩 아이콘 색상을 노란색으로 변경하는 방법은 무엇입니까?

분류에서Dev

텍스트 상자 색상을 검정색으로 유지하는 방법은 무엇입니까?

분류에서Dev

행과 열의 인덱스로 테이블 셀의 색상을 변경하는 방법은 무엇입니까?

분류에서Dev

버튼 클릭으로 텍스트 색상을 변경하는 방법은 무엇입니까?

분류에서Dev

스타일러스에서 색상 이름이 자동으로 16 진수 값으로 변환되지 않도록하는 방법은 무엇입니까?

분류에서Dev

충돌 감지로 캔버스 채우기 스타일을 변경하는 방법은 무엇입니까?

분류에서Dev

인스턴스화 된 타일 프리 팹을 비활성화 된 타일에서 활성 타일로 교환하는 방법은 무엇입니까?

분류에서Dev

인라인 스타일을 동적으로 재정의하는 방법은 무엇입니까?

분류에서Dev

인라인 스타일을 동적으로 재정의하는 방법은 무엇입니까?

분류에서Dev

캔버스 요소의 "Z- 색인"을 설정하는 방법은 무엇입니까?

분류에서Dev

AngularJS-상자 그림자의 색상을 ng 스타일로 바꾸는 방법은 무엇입니까?

분류에서Dev

탐색 메뉴 링크 스타일을 지속적으로 유지하는 방법은 무엇입니까?

분류에서Dev

마지막에 링크 목록을 포함하는 번호 인용 스타일과 같이 프린터 친화적 인 방식으로 링크 출력을 얻는 방법은 무엇입니까?

분류에서Dev

캔버스에 굵은 / 색상으로 된 일부 단어로 여러 줄 텍스트를 그리는 방법은 무엇입니까?

분류에서Dev

SWIFTUI. 클릭 후 버튼의 색상을 영구적으로 변경하는 방법은 무엇입니까?

분류에서Dev

스타일 구성 요소의 스타일을 동적으로 변경하는 방법은 무엇입니까?

분류에서Dev

클릭 후 일시적으로 Android 버튼 스타일을 변경하는 방법은 무엇입니까?

분류에서Dev

Angularjs 지시문을 사용하여 동적 값을 기반으로 텍스트 색상을 변경하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    Android에서 캔버스의 색상을 5 초마다 동적으로 변경하는 방법은 무엇입니까?

  2. 2

    Tkinter 캔버스에서 닫힌 폴리 라인의 색상을 지정하는 방법은 무엇입니까?

  3. 3

    색맹 친화적 인 30 가지 고유 한 색상을 생성하는 방법은 무엇입니까?

  4. 4

    바닐라 자바 스크립트를 사용하여 인라인 SVG의 색상을 동적으로 변경하는 방법은 무엇입니까?

  5. 5

    대화 상자에서 캔버스를 인스턴스화하는 방법은 무엇입니까?

  6. 6

    jQuery Mobile에서 링크 텍스트 색상을 동적으로 변경하는 방법은 무엇입니까?

  7. 7

    동적으로 생성 된 값의 텍스트 색상을 변경하는 방법은 무엇입니까? -PHP

  8. 8

    Google 차트 캔들 스틱으로 세로선의 색상을 변경하는 방법은 무엇입니까?

  9. 9

    jquery에서 인라인 스타일 테두리 색상을 얻는 방법은 무엇입니까?

  10. 10

    NSAttributedString (ios)에서 밑줄 스타일에 색상을 적용하는 방법은 무엇입니까?

  11. 11

    픽셀 색상을 기반으로 RGB 이미지의 부울 마스크를 생성하는 가장 비단뱀적인 방법은 무엇입니까?

  12. 12

    부트 스트랩 아이콘 색상을 노란색으로 변경하는 방법은 무엇입니까?

  13. 13

    텍스트 상자 색상을 검정색으로 유지하는 방법은 무엇입니까?

  14. 14

    행과 열의 인덱스로 테이블 셀의 색상을 변경하는 방법은 무엇입니까?

  15. 15

    버튼 클릭으로 텍스트 색상을 변경하는 방법은 무엇입니까?

  16. 16

    스타일러스에서 색상 이름이 자동으로 16 진수 값으로 변환되지 않도록하는 방법은 무엇입니까?

  17. 17

    충돌 감지로 캔버스 채우기 스타일을 변경하는 방법은 무엇입니까?

  18. 18

    인스턴스화 된 타일 프리 팹을 비활성화 된 타일에서 활성 타일로 교환하는 방법은 무엇입니까?

  19. 19

    인라인 스타일을 동적으로 재정의하는 방법은 무엇입니까?

  20. 20

    인라인 스타일을 동적으로 재정의하는 방법은 무엇입니까?

  21. 21

    캔버스 요소의 "Z- 색인"을 설정하는 방법은 무엇입니까?

  22. 22

    AngularJS-상자 그림자의 색상을 ng 스타일로 바꾸는 방법은 무엇입니까?

  23. 23

    탐색 메뉴 링크 스타일을 지속적으로 유지하는 방법은 무엇입니까?

  24. 24

    마지막에 링크 목록을 포함하는 번호 인용 스타일과 같이 프린터 친화적 인 방식으로 링크 출력을 얻는 방법은 무엇입니까?

  25. 25

    캔버스에 굵은 / 색상으로 된 일부 단어로 여러 줄 텍스트를 그리는 방법은 무엇입니까?

  26. 26

    SWIFTUI. 클릭 후 버튼의 색상을 영구적으로 변경하는 방법은 무엇입니까?

  27. 27

    스타일 구성 요소의 스타일을 동적으로 변경하는 방법은 무엇입니까?

  28. 28

    클릭 후 일시적으로 Android 버튼 스타일을 변경하는 방법은 무엇입니까?

  29. 29

    Angularjs 지시문을 사용하여 동적 값을 기반으로 텍스트 색상을 변경하는 방법은 무엇입니까?

뜨겁다태그

보관