2017-03-11 10 views
2

캔버스의 SVG 필터 구현에서 작업하고 있지만 복합 산술 연산자에 두 가지 문제가 있습니다.캔버스의 feCposite 필터 구현

이 연산자에 대한 나의 구현은 W3C specification과 firefox9 소스 코드를 기반으로합니다. 여기

이 필터 &는 SVG exemple 내 코드 : Fiddle complete code

var k1Scaled = options.k1/255; 
var k4Scaled = options.k4 * 255; 
for(v=0; v<datas.length; v+=4) { 
    r = datasB1[v+0]; 
    g = datasB1[v+1]; 
    b = datasB1[v+2]; 
    a = datasB1[v+3]; 
    r1 = datasB2[v+0]; 
    g1 = datasB2[v+1]; 
    b1 = datasB2[v+2]; 
    a1 = datasB2[v+3]; 
    //if (a === 0 && a1 === 0) continue; 
    vR = k1Scaled * r1 * r + options.k2 * r + options.k3 * r1 + k4Scaled; 
    vG = k1Scaled * g1 * g + options.k2 * g + options.k3 * g1 + k4Scaled; 
    vB = k1Scaled * b1 * b + options.k2 * b + options.k3 * b1 + k4Scaled; 
    vA = k1Scaled * a1 * a + options.k2 * a + options.k3 * a1 + k4Scaled; 
    datas[v+0] = Math.min(Math.max(0, ~~vR), 255); 
    datas[v+1] = Math.min(Math.max(0, ~~vG), 255); 
    datas[v+2] = Math.min(Math.max(0, ~~vB), 255); 
    datas[v+3] = Math.min(Math.max(0, ~~vA), 255); 
} 

내 첫번째 문제 : 나 투명 화소의 화학식을 분해하는 경우 I 인해 화학식 투명 화소 실버 색상이 결과는 :

결과 = K1의 *의 I1 *의 I2 + K2 *는 I1 + K3의 * I2 + K4

K1 =/255 = 0.0019, 0.5, I1 = 0, I2 = 0, K2 = 0.5, K3 = 0.5 , k4 = 0.5 * 255 = 127

,

결과 = 0.0019 * 0 * 0 + 0.5 * 0 + 0.5 * 0 + 127 = 127 => RGBA 실버

내 두번째 문제점 : 결과는 SVG exemple보다 불투명 내가 가정 웹 브라우저 사전 곱셈 rgba 결과하지만이 시도하지만 아무 결과.

캔버스에 적용된 svg 필터를 사용할 수 없으며 순수한 자바 스크립트/캔버스 구현이 필요합니다.

아이디어 나 해결책이있는 경우 미리 감사드립니다.

크란.

+0

캔버스에 적용된 svg 필터를 사용할 수없는 이유는 무엇입니까? 'ctx.filter ='문서의 svg 파일을 가리 키도록 [컨텍스트의 필터] (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter)를 설정할 수 있다는 것을 알고 있습니다. (#yourSvgFilter) '' – Kaiido

+0

Michael, Kaiido에게 감사드립니다. 크롬이 캔버스, 파이어 폭스 및 즉 충돌에서 여러 개의 svg 필터를 올바르게 적용 할 수 있습니다. 이는 순수한 자바 스크립트에서 구현 한 이유입니다. – kran

+0

FF가 충돌하면 버그 보고서를 엽니 다. 버그 질라. – Kaiido

답변

0

Here the solution

this._arithmetic = function(options, ctx) { 
    var b1, ctxB1, ctxB2, w, h, x, y, v, imgDatas, datas, imgDatasB1, datasB1, imgDatasB2, datasB2; 
    b1 = document.createElement("canvas"); 
    ctxB1 = b1.getContext("2d"); 
    ctxB1.resize(this.width,this.height); 
    ctxB1.drawImage(options.in.source, options.in.options.x, options.in.options.y, options.in.options.width, options.in.options.height); 
    imgDatasB1 = ctxB1.getImageData(0,0,this.width,this.height); 
    this.premultiply(imgDatasB1); 
    datasB1 = imgDatasB1.data; 

    b2 = document.createElement("canvas"); 
    ctxB2 = b2.getContext("2d"); 
    ctxB2.resize(this.width,this.height); 
    ctxB2.drawImage(options.in2.source, options.in2.options.x, options.in2.options.y, options.in2.options.width, options.in2.options.height); 
    ctx.resize(this.width,this.height); 
    ctx.drawImage(b2, 0, 0); 
    imgDatas = ctx.getImageData(0,0,this.width,this.height); 
    this.premultiply(imgDatas); 
    datas = imgDatas.data; 
    var k1Scaled = options.k1/255; 
    var k4Scaled = options.k4 * 255; 
    var vR,vG,vB,vA,r,g,b,a,r1,g1,b1,a1; 
    for(v = 0;v < datas.length;v += 4) { 
    r = datasB1[v + 0]; 
    g = datasB1[v + 1]; 
    b = datasB1[v + 2]; 
    a = datasB1[v + 3]; 

    r1 = datas[v + 0]; 
    g1 = datas[v + 1]; 
    b1 = datas[v + 2]; 
    a1 = datas[v + 3]; 

    vR = k1Scaled * r1 * r + options.k2 * r + options.k3 * r1 + k4Scaled; 
    vG = k1Scaled * g1 * g + options.k2 * g + options.k3 * g1 + k4Scaled; 
    vB = k1Scaled * b1 * b + options.k2 * b + options.k3 * b1 + k4Scaled; 
    vA = k1Scaled * a1 * a + options.k2 * a + options.k3 * a1 + k4Scaled; 

    vR = vR < 0 ? 0 : vR > 255 ? 255 : vR; 
    vG = vG < 0 ? 0 : vG > 255 ? 255 : vG; 
    vB = vB < 0 ? 0 : vB > 255 ? 255 : vB; 
    vA = vA < 0 ? 0 : vA > 255 ? 255 : vA; 

    datas[v + 0] = vR; 
    datas[v + 1] = vG; 
    datas[v + 2] = vB; 
    datas[v + 3] = vA; 
    } 
    this.unPremultiply(imgDatas); 
    ctx.putImageData(imgDatas,0,0); 
}; 

전치 승산/Unpremultiply는 함수의 코드는 바이올린 링크입니다.