2016-11-16 42 views
2

有人可以幫我解決這個問題嗎? 我想應用alpha圖層蒙版,使一些圖像透明使用畫布。如何應用阿爾法圖層蒙版,使一些圖像透明使用畫布

非常感謝。

var redImageData = redCanvas.getContext("2d").getImageData(0, 0, 200, 200); //overlay 
    var ImageData = imageCanvas.getContext("2d").getImageData(0, 0, 200, 200); 

var px = redImageData.data; 
var px2 = ImageData.data; 
for(var i = 0; i < px.length; i += 4) { 
    if(px[i + 0] == 0 && px[i + 1] == 0 && px[i+2] == 0){ 
     px[i + 3] = 0; 
    } else { 
     px[i + 0] = px2[i + 0]; 
     px[i + 1] = px2[i + 1]; 
     px[i + 2] = px2[i + 2]; 
     px[i + 3] = px2[i + 3]; 
    } 
} 
ctx.imageSmoothingEnabled = true; 
ctx.putImageData(redImageData, 0, 0); 

alpha遮罩過於https://i.stack.imgur.com/zCzOf.png

+1

改變您的圖像,使得白色部分是透明的,然後使用['globalCompositeOperation'](https://developer.mozilla.org/en-US/docs/Web/API/ CanvasRenderingContext2D/globalCompositeOperation)來執行合成。 – Kaiido

回答

1

鏈接的圖像是不是一個真正的阿爾法掩模但磨砂圖像。不同之處在於,無光澤圖像代表作爲alpha通道,但將其顯示爲RGB(或灰度)組件。它實際上並沒有alpha通道。無光澤圖像在視頻合成軟件中很常見,但在網絡上不太實用。

畫布或其使用的Porter-Duff方法不直接支持亞光圖像,因此必須先將其轉換爲實際的Alpha通道。要做到這一點,你必須迭代每個像素,並將其中一個分量值(從紅色,綠色或藍色 - 無所謂)放入alpha通道。

完成後,您可以使用現在具有合適alpha通道的畫布對象以及僅使用alpha信息的混合操作(混合模式是不同的章節)。

更好的方法當然是提供圖像作爲PNG與適當的alpha通道。但在任何情況下,以顯示它有可能也採用磨砂圖像工作,但效率不高,我們可以做到以下幾點:

轉換無光澤的圖案爲Alpha通道

第一步:此代碼段展示瞭如何可以高效地完成將無光澤圖像轉換爲Alpha通道的預備步驟。正如已經提到的那樣,最終的顏色對於主合成步驟來說並不重要,因爲它僅使用alpha通道。

只需確保圖像在嘗試使用圖像之前已正確加載,方法是使用圖像的onload回調或在加載所有內容後運行腳本。

此代碼將使用像素的全部32位值(爲了提高效率)簡單地將組件(在本例中爲藍色)轉換爲alpha通道,使圖像看起來像是青色的,但使用正確的alpha,如您所見通過橙色背景顯示(儘管大部分代碼是處理加載和設置的)。

window.onload = function() { 
 

 
    // at this stage the image has loaded: 
 
    var img = document.getElementById("img"); 
 
    var canvas = document.getElementById("c"); 
 
    var ctx = canvas.getContext("2d"); 
 

 
    // - setup canvas to match image 
 
    canvas.width = img.naturalWidth; 
 
    canvas.height = img.naturalHeight; 
 

 
    // - draw image 
 
    ctx.drawImage(img, 0, 0); 
 

 
    // CONV. STEP: move a component channel to alpha-channel 
 
    var idata = ctx.getImageData(0, 0, canvas.width, canvas.height); 
 
    var data32 = new Uint32Array(idata.data.buffer); 
 
    var i = 0, len = data32.length; 
 
    
 
    while(i < len) { 
 
    data32[i] = data32[i++] << 8; // shift blue channel into alpha (little-endian) 
 
    } 
 
    
 
    // update canvas 
 
    ctx.putImageData(idata, 0, 0);  
 
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
 
<canvas id="c"></canvas>

復化

然後,第二部分成爲如何使用新的alpha通道合成。

在這種情況下,無光澤圖像的黑色變得完全透明,而白色變得完全不透明。您可以在轉換步驟中將其逆轉,但只要您瞭解無光澤圖像的外觀,就不會真正消光。

要替換我們使用合成模式source-in的內部內容。這會根據alpha值取代內容,同時保持alpha通道的狀態。

首先使用相同的模式處理內部部分,使我們可以在繪製框架之前對內容做額外的事情(認爲暈影,陰影等)。

作爲最後一步,我們通過使用複合模式destination-over來填充透明區域和框架本身,該模式替換了更多透明區域,其中內容被繪製到畫布上(概念上它在現有內容後面繪製)。

下面的代碼使用簡單的彩色框 - 只需用你想繪製的任何東西替換它們即可。

window.onload = function() { 
 
    var img = document.getElementById("img"); 
 
    var canvas = document.getElementById("c"); 
 
    var ctx = canvas.getContext("2d"); 
 
    canvas.width = img.naturalWidth; 
 
    canvas.height = img.naturalHeight; 
 
    ctx.drawImage(img, 0, 0); 
 

 
    var idata = ctx.getImageData(0, 0, canvas.width, canvas.height); 
 
    var data32 = new Uint32Array(idata.data.buffer); 
 
    var i = 0, len = data32.length; 
 
    while(i < len) data32[i] = data32[i++] << 8; 
 
    ctx.putImageData(idata, 0, 0); 
 
    
 
    // COMP. STEPS: use the mask with composite operation. Since our frame 
 
    // is black (= transparent as alpha) we can use the following mode: 
 
    ctx.globalCompositeOperation = "source-in"; 
 
    
 
    // draw something, here a blue box, replace with whatever you want 
 
    ctx.fillStyle = "blue"; 
 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
 
    
 
    // to fill the frame area, still transparent, use this mode: 
 
    ctx.globalCompositeOperation = "destination-over"; 
 
    ctx.fillStyle = "yellow"; 
 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
 
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
 
<canvas id="c"></canvas>