2014-07-14 20 views
8

cho hai canvas có cùng kích thước pixel, trong đó canvas1 chứa hình ảnh tùy ý (jpg, png hoặc như vậy) và canvas2 chứa pixel đen và không phải màu đen.Kết hợp ảnh canvas và mặt nạ alpha vải vào dataurl được tạo ra png

những gì tôi muốn đạt được: sử dụng một canvas3 thứ ba tôi muốn sao chép canvas1 và có mỗi điểm ảnh canvas2 đen (có thể bao gồm một ngưỡng cửa của bóng tối) phải minh bạch trong canvas3

tôi đã có một giải pháp làm việc như thế này:

canvas3context.drawImage(canvas1,0,0); 
var c3img = canvas3context.getImageData(0,0,canvas3.width,canvas3.height); 
var c2img = canvas2context.getImageData(0,0,canvas2.width,canvas2.height); 
loop(){ 
    if(c2img i-th,i+1-th,i+2-th pixel is lower than threshold) 
     set c3img.data[i]=c3img.data[i+1]=c3img.data[i+2]=c3img.data[i+3]=0 
} 

vấn đề với trên (giả) mã là, rằng nó là chậm vì vậy câu hỏi của tôi là: bất cứ ai có thể chia sẻ một ý tưởng làm thế nào để tăng tốc độ này tăng lên đáng kể? tôi nghĩ về webgl nhưng tôi không bao giờ làm việc với nó - vì vậy tôi không có ý tưởng về shaders hoặc các công cụ hoặc các điều khoản cần thiết cho việc này. ý tưởng khác là có lẽ tôi có thể chuyển đổi canvas2 sang màu đen & trắng bằng cách nào đó rất nhanh (không chỉ modifieng mỗi điểm ảnh trong một vòng lặp như ở trên) và làm việc với chế độ pha trộn để tạo ra các điểm ảnh trong suốt

bất kỳ sự giúp đỡ được đánh giá cao

+0

Một vấn đề khác với việc lặp lại pixel là đọc dữ liệu ảnh canvas có thể chạy vào vấn đề gốc chéo. –

Trả lời

7

trả lời câu hỏi của riêng tôi, tôi cung cấp giải pháp để hợp nhất một hình ảnh tùy ý với hình ảnh màu trắng & màu đen. những gì im vẫn còn thiếu là làm thế nào để thiết lập các kênh alpha cho chỉ là một màu sắc của một canvas.

Tôi đặt câu hỏi theo từng phần và trả lời từng câu hỏi.

Câu hỏi 1: Cách chuyển canvas thành màu xám không lặp lại từng pixel?

Trả lời: vẽ hình ảnh trên một vải trắng với chế độ hòa trộn 'sáng'

function convertCanvasToGrayscale(canvas){ 
    var tmp = document.createElement('canvas'); 
    tmp.width = canvas.width; 
    tmp.height = canvas.height; 
    var tmpctx = tmp.getContext('2d'); 

    // conversion 
    tmpctx.globalCompositeOperation="source-over"; // default composite value 
    tmpctx.fillStyle="#FFFFFF"; 
    tmpctx.fillRect(0,0,canvas.width,canvas.height); 
    tmpctx.globalCompositeOperation="luminosity"; 
    tmpctx.drawImage(canvas,0,0); 

    // write converted back to canvas 
    ctx = canvas.getContext('2d'); 
    ctx.globalCompositeOperation="source-over"; 
    ctx.drawImage(tmp, 0, 0); 
} 

Câu hỏi 2: Làm thế nào để chuyển đổi một vải màu xám thành màu đen & trắng mà không lặp lại mỗi điểm ảnh?

Trả lời: hai lần màu né tránh sự pha trộn chế độ với #FEFEFE màu sẽ làm công việc

function convertGrayscaleCanvasToBlackNWhite(canvas){ 
    var ctx = canvas.getContext('2d'); 

    // in case the grayscale conversion is to bulky for ya 
    // darken the canvas bevore further black'nwhite conversion 
    //for(var i=0;i<3;i++){ 
    // ctx.globalCompositeOperation = 'multiply'; 
    // ctx.drawImage(canvas, 0, 0); 
    //} 

    ctx.globalCompositeOperation = 'color-dodge'; 
    ctx.fillStyle = "rgba(253, 253, 253, 1)"; 
    ctx.beginPath(); 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
    ctx.fill(); 
    ctx.globalCompositeOperation = 'color-dodge'; 
    ctx.fillStyle = "rgba(253, 253, 253, 1)"; 
    ctx.beginPath(); 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
    ctx.fill(); 
} 

Lưu ý: chức năng này giả định rằng bạn muốn khu vực đen trái màu đen và mỗi điểm ảnh không đen trở thành màu trắng! do đó, hình ảnh màu xám không có màu đen sẽ trở thành màu trắng hoàn toàn lý do tôi chọn thao tác này là nó hoạt động tốt hơn trong trường hợp của tôi và chỉ sử dụng hai hoạt động pha trộn có nghĩa là nó khá nhanh - nếu bạn muốn có nhiều pixel đen hơn nhiều pixel trắng trở thành màu trắng, bạn có thể sử dụng chú thích cho vòng lặp để làm tối hình ảnh trước. do đó, pixel tối sẽ trở thành màu đen và sáng hơn pixel trở nên tối hơn. khi bạn tăng số lượng của việc sử dụng màu đen dodge pixel một lần nữa sẽ làm phần còn lại của công việc

Câu hỏi 3: Làm thế nào để hợp nhất một màu đen & vải trắng với một vải mà không iterating mỗi điểm ảnh?

Trả lời: sử dụng 'nhân' chế độ pha trộn

function getBlendedImageWithBlackNWhite(canvasimage, canvasbw){ 
    var tmp = document.createElement('canvas'); 
    tmp.width = canvasimage.width; 
    tmp.height = canvasimage.height; 

    var tmpctx = tmp.getContext('2d'); 

    tmpctx.globalCompositeOperation = 'source-over'; 
    tmpctx.drawImage(canvasimage, 0, 0); 

    // multiply means, that every white pixel gets replaced by canvasimage pixel 
    // and every black pixel will be left black 
    tmpctx.globalCompositeOperation = 'multiply'; 
    tmpctx.drawImage(canvasbw, 0, 0); 

    return tmp; 
} 

Câu hỏi 4: Làm thế nào để đảo ngược một Đen & vải trắng mà không iterating mỗi điểm ảnh?

trả lời: Chế độ sử dụng 'khác biệt' pha trộn

function invertCanvas(canvas){ 
    var ctx = canvas.getContext("2d"); 

    ctx.globalCompositeOperation = 'difference'; 
    ctx.fillStyle = "rgba(255, 255, 255, 1)"; 
    ctx.beginPath(); 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
    ctx.fill(); 
} 

nay đến 'hợp nhất' một canvasimage với một canvasmask ai có thể làm

convertCanvasToGrayscale(canvasmask); 
convertGrayscaleCanvasToBlackNWhite(canvasmask); 
result = getBlendedImageWithBlackNWhite(canvasimage, canvasmask); 

liên quan đến hiệu suất: rõ ràng là những chế độ pha trộn nhanh hơn nhiều so với modifieng mỗi pixel và để có tốc độ nhanh hơn một chút, có thể đóng gói tất cả các chức năng cùng nhau khi cần thiết thành một hàm và chỉ tái chế một tmpcanvas - nhưng đó là eader ^^

như một sidenote: i kiểm tra như thế nào kích thước của png kết quả khác với khi bạn so sánh trên là kết quả getBlendedImageWithBlackNWhite với hình ảnh tương tự nhưng các lĩnh vực đen được thực hiện minh bạch bằng cách lặp lại mỗi pixel và thiết lập các kênh alpha sự khác biệt về kích thước gần như không có gì và do đó nếu bạn không thực sự cần mặt nạ alpha thông tin mà mọi pixel đen có nghĩa là trong suốt có thể đủ để xử lý thêm

lưu ý: người ta có thể đảo ngược ý nghĩa của màu đen và trắng bằng invertCanvas() function

nếu bạn muốn biết thêm lý do tại sao tôi sử dụng các chế độ hòa trộn hoặc cách pha trộn mo des thực sự làm việc bạn nên kiểm tra toán học đằng sau họ - IMHO bạn không thể phát triển các chức năng như vậy nếu ya không biết làm thế nào họ thực sự làm việc: math behind blend modes canvas composition standard including a bit math

cần một ví dụ - nhận ra sự khác biệt: http://jsfiddle.net/C3fp4/1/

+0

Công cụ tuyệt vời. Lưu ý một số bộ lọc GlobalCompositeOperation này không hoạt động trong safari. – Mulhoon

Các vấn đề liên quan