2014-07-14 32 views
8

podane dwa płótno o tym samym rozmiarze piksela, gdzie canvas1 zawiera dowolny obraz (jpg, png lub podobny) i canvas2 zawiera czarne i nie czarne piksele.Scal płótno i płótno maski alfa w dataurl wygenerowane png

co chcę achive: za pomocą trzeciego canvas3 chcę sklonować canvas1 i mają wszelkie czarne canvas2 piksel (może w tym progu ciemności) być przezroczyste w canvas3

mam już roztwór roboczy takiego:

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 
} 

problem z powyższym (pseudo) kod jest, że jest powolny więc moje pytanie brzmi: każdy może podzielić się pomysł, jak to przyspieszyć znacząco? Myślałem o webgl, ale nigdy z nim nie pracowałem - więc nie mam pojęcia o shaderów ani narzędziach i terminach potrzebnych do tego. Innym pomysłem było to, że może mógłbym konwertować canvas2 do czerni & biały jakoś bardzo szybko (nie tylko modifieng każdy piksel w pętli jak wyżej) i pracować z trybów mieszania do wygenerowania przezroczyste piksele

każda pomoc jest bardzo ceniona

+0

Kolejny problem z iteracyjnymi pikselami polega na tym, że odczytanie obrazu na płótnie może napotkać problem z krzyżowym początkiem. –

Odpowiedz

7

odpowiadając na moje własne pytanie, zapewniam rozwiązanie do scalania dowolnego obrazu z czarnym białym obrazem &. to, czego wciąż brakuje, to jak ustawić kanał alfa dla tylko jednego koloru płótna.

Rozdzielam pytanie na części i odpowiadam na nie.

Pytanie 1: Jak przekonwertować płótno do skali szarości bez iteracji każdy piksel?

Odpowiedź: narysować obraz na białym płótnie z trybu mieszania „jasności”

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); 
} 

Pytanie 2: Jak przekonwertować szarości płótno na czarno & biały bez iteracji każdy piksel?

Odpowiedź: dwa razy kolor Dodge tryb mieszania z kolorowym #FEFEFE wykona pracę

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(); 
} 

Uwaga: Funkcja ta zakłada, że ​​chcesz czarne obszary lewy czarny i każdy non-czarny piksel stać się białym! w ten sposób obraz w skali szarości, który nie ma czarnego piksela, stanie się całkowicie biały Powodem, dla którego wybrałem tę operację jest to, że działa lepiej w moim przypadku i użycie tylko dwóch operacji mieszania oznacza, że ​​jest dość szybki - jeśli chcesz, aby więcej ciemnego piksela pozostało czarne i bardziej biały piksel staje się biały, możesz użyć zapętlonej pętli, aby wcześniej przyciemnić obraz. w ten sposób ciemny piksel stanie się czarny, a jaśniejszy piksel stanie się ciemniejszy. jak zwiększyć ilość czarny piksel za pomocą koloru i Dodge'a ponownie wykona resztę zadania

Pytanie 3: Jak scalić Czarny & białym płótnie z innym płótnie bez iteracji każdy piksel?

Odpowiedź: stosowanie 'pomnożyć' tryb mieszania

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; 
} 

Pytanie 4: Jak odwrócić Czarny & białego płótna bez iteracji każdy piksel?

Odpowiedź: Tryb stosowanie 'różnica' mieszanka

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(); 
} 

teraz do 'scalenia' na canvasimage z canvasmask można zrobić

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

dotyczących wydajności: Oczywiście te tryby mieszania są znacznie szybsze niż modyfikowanie każdego piksela i aby uzyskać nieco szybszy można spakować wszystkie funkcje razem w razie potrzeby do jednej funkcji i odtworzyć tylko jeden tmpcanvas - ale to pozostało do eader ^^

jak sidenote: i testowano jak wielkość wynikającą png różni jeśli porównać powyżej znajduje getBlendedImageWithBlackNWhite wynik z tego samego obrazu, ale czarne obszary są przejrzyste przez powtarzanie każdy piksel i ustawiania kanału alfa różnicę Rozmiar jest prawie zerowy, a więc jeśli naprawdę nie potrzebujesz maski alfa, informacja, że ​​każdy czarny piksel ma być przezroczysty, może być wystarczająca do dalszego przetwarzania. Uwaga: można odwrócić znaczenie czerni i bieli za pomocą Funkcja invertCanvas()

jeśli chcesz wiedzieć więcej o tym, dlaczego używam tych trybów mieszania lub jak mieszać mo des naprawdę działa należy sprawdzić matematyki za nimi - imho nie jesteś w stanie opracować takie funkcje, jeśli ya nie wiem jak one naprawdę działają: math behind blend modes canvas composition standard including a bit math

potrzebują przykład - dostrzec różnicę: http://jsfiddle.net/C3fp4/1/

+0

Świetne rzeczy. Uwaga: niektóre z tych filtrów globalCompositeOperation nie działają jeszcze w Safari. – Mulhoon