2013-01-01 10 views
6

Ho notato uno strano problema con getImageData; la trasparenza dell'immagine sembra essere ignorata quando i dati dell'immagine vengono recuperati.Trasparenza persa con getImageData - HTML5 2d Contesto

Poiché ogni immagine deve essere disegnato su un canvas prima i dati di immagine possono essere ottenuti, ho assunto questo era un problema con la canvas in questione è opaca. Ma mi sbagliavo, dal momento che l'utilizzo di canvas come argomento in drawImage mantiene la trasparenza.

Ecco come ho caricato l'immagine;

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

Il callback è semplicemente la funzione di disegno, che invoca draw_image per disegnare l'immagine.

La versione normale;

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

Si prende semplicemente la tela come argomento per drawImage, e il risultato è come previsto con trasparenza mantenuta. Example.

Versione dati immagine;

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

Questo ottiene i dati di immagine del rettangolo richiesto dalla stessa tela di quello utilizzato nella versione al solito, e mette i dati di immagine sulla tela voglio disegnare a. Credo che la trasparenza debba essere mantenuta, ma non è così. Example. (Questo è un collegamento Dropbox a causa del flag origin-clean.)

Mi sbaglio nell'assumere che la trasparenza debba essere mantenuta con getImageData? O lo sto solo usando in modo sbagliato?

In entrambi i casi, l'aiuto sarebbe davvero apprezzato.

risposta

7

Credo che il tuo problema è che putImageData non usa uno composite operation per fondere i dati dell'immagine di origine e di destinazione. Piuttosto, sta facendo una scrittura diretta dei canali rosso, verde, blu, e alpha nell'area di disegno. Per i pixel completamente trasparenti, ciò significa che possono apparire o meno nel colore che ti aspetti.

Invece, è possibile creare un elemento di tela intermedio, disegnare su di esso e quindi utilizzare drawImage() per renderlo nell'area di disegno di destinazione con l'applicazione globaleComposite appropriata applicata. Mask for putImageData with HTML5 canvas? discute questo problema in modo più dettagliato.

Aggiornamento: è possibile verificare che i dati che si stanno scrivendo nel vostro esempio "rotto" in realtà hanno dati trasparenti in esso facendo ctx.getImageData(230,50,1,1).data. Il risultato è [0,0,0,0] - cioè un pixel completamente trasparente.

+1

Vedo, questo lo spiega! Grazie per la tua risposta! Anche se, questo davvero getta una chiave inglese nei lavori. Stavo pensando di testare se i benefici dell'uso di 'canvas' come 'immagini' nei giochi (mascheramento del colore e trasformazione prospettica senza contesto) superino il sovraccarico o meno. Se ho bisogno di introdurre una tela intermedia per disegnare l'immagine trasformata, potrei anche limitarmi a usare gli oggetti 'Image' e una' tela' grezza per l'elaborazione. Grazie ancora! – Rikonator