2013-01-01 16 views
6

Zauważyłem dziwny problem z getImageData; przezroczystość obrazu wydaje się być ignorowana podczas pobierania danych obrazu.Przejrzystość utracona z getImageData - Kontekst 2d HTML5

Ponieważ jakiekolwiek zdjęcie musi zostać narysowane na canvas, zanim można uzyskać jego dane obrazu, założyłem, że był to problem związany z tym, że dany obiekt canvas jest nieprzejrzysty. Ale myliłem się, ponieważ używanie canvas jako argumentu w drawImage zachowuje przezroczystość.

Oto jak załadowałem obraz;

var load_image = function(name, url, holder, callback) { 
    var img = new Image(); 
    img.src = url; 

    img.addEventListener('load', function(e) { 
     var canvas = make_canvas(e.target.width, e.target.height); 
     var ctx = canvas.getContext('2d'); 

     ctx.clearRect(0, 0, canvas.width, canvas.height); 
     ctx.drawImage(e.target, 0, 0); 

     holder[name] = {canvas: canvas, ctx: ctx}; 

     delete e.target; 

     callback.call(); 
    }, false); 
}; 

callback po prostu funkcja draw, co wywołuje draw_image zwrócić obrazu.

Zwykła wersja;

var draw_image = function(ctx, img, sx, sy, w, h, dx, dy) { 
    ctx.drawImage(img.canvas, sx, sy, w, h, dx, dy, w, h); 
}; 

To po prostu bierze płótno jako argument dla drawImage, a wynik jest przeznaczony przejrzystości utrzymane. Example.

Wersja danych obrazu;

var draw_image = function(ctx, img, sx, sy, w, h, dx, dy) { 
    var imagedata = img.ctx.getImageData(sx, sy, w, h); 
    ctx.putImageData(imagedata, dx, dy); 
}; 

ten uzyskuje dane obrazu wymaganego prostokąta z tego samego płótna, jak stosowany w zwykłej wersji, i umieszcza dane obrazu na płótnie chcę zwrócić. Uważam, że należy zachować przejrzystość, ale tak nie jest. Example. (To jest link do Dropbox z powodu flagi origin-clean).

Czy nie mam racji zakładając, że przejrzystość powinna być utrzymywana przy pomocy getImageData? Czy po prostu używam go w niewłaściwy sposób?

Tak czy inaczej, pomoc byłaby naprawdę doceniana.

Odpowiedz

7

Uważam, że twój problem polega na tym, że putImageData nie używa composite operation do mieszania źródłowych i docelowych danych obrazu. Raczej robi bezpośredni zapis kanałów w kolorze czerwonym, zielonym, niebieskim, i alfa. W przypadku całkowicie przezroczystych pikseli oznacza to, że mogą one nie być widoczne w oczekiwanym kolorze.

Zamiast tego można utworzyć pośredni element canvas, narysować do niego, a następnie użyć funkcji drawImage() w celu renderowania tego do docelowego obszaru roboczego za pomocą odpowiedniej operacji globalCompositeOperation, która zostanie zastosowana. Mask for putImageData with HTML5 canvas? omawia ten problem bardziej szczegółowo.

Aktualizacja: Możesz zweryfikować, że dane, które zapisujesz w swoim "uszkodzonym" przykładzie, mają w rzeczywistości przezroczyste dane, wykonując ctx.getImageData(230,50,1,1).data. Wynikiem jest [0,0,0,0] - czyli w pełni przezroczysty piksel.

+1

Rozumiem, że to wyjaśnia! Dzięki za odpowiedź! Chociaż to naprawdę rzuca klucz do dzieł. Miałem zamiar przetestować, czy korzyści z używania "canvas" jako "obrazów" w grach (maskowanie kolorów i transformacja perspektywy bez kontekstu) przeważają nad narzutem, czy nie. Jeśli potrzebuję wprowadzić płótno pośrednie, aby narysować przekształcony obraz, równie dobrze mogę trzymać się przy przetwarzaniu obiektów 'Obraz' i szorstkiego' płótna'. Dzięki jeszcze raz! – Rikonator