
Maceo, 2005
Comecei a programar muito cedo. E quando criança, mas já com meu super
TK3000 2e, a experiência de manipular cada pixel da tela foi revolucionária. No meu raciocínio infantil, se eu tinha o IF, o GOTO e o ‘poder’ sobre qualquer pixel da tela, então eu poderia fazer qualquer coisa com o computador. Hoje, mesmo sabendo que meu pensamento era no mínimo inocente, não posso deixar de reconhecer alguma lógica nele. E ainda afirmo: a possibilidade de manipular qualquer pixel é libertadora!

.
Porém quem começa a trabalhar com o elemento Canvas do HTML5 percebe que parece faltar funções do gênero setPixel e getPixel.
Mas existe salvação. Por sorte é possível obter e registrar um array de cores que representa cada pixel do canvas. Na realidade, esta técnica já foi até utilizada aqui no post: Como compactar Código Javascript em um PNG.
A seguir veremos, passo a passo, como obter, modificar e registrar o array de pixels do canvas. Ao final mostrarei o código do bitMapCanvas, que criei contendo as úteis e inexistentes funções setPixel e getPixel.
Como havia dito, o segredo é saber como obter do canvas e registrar no canvas o array representando a imagem e seus pixels. Segue abaixo o código exemplificando como obter tal array:
//obtem objeto canvas
cnv = document.getElementById(psIdCanvas);
//obtem o contexto 2d
ctx = cnv.getContext('2d');
//pega os valores de altura e largura do canvas
w=parseInt(cnv.width);
h=parseInt(cnv.height);
//cria ou obtem o array de pixels
if (ctx.createImageData) {
img = ctx.createImageData(w, h);
} else if (ctx.getImageData) {
img = ctx.getImageData(0, 0, w, h);
} else {
img = {'width' : w, 'height' :h, 'data' : new Array(w*h*4)};
}
//a variavel arrPix é o seu array de pixels
arrPix = img.data
Do exemplo acima temos um array de dimensão w*h*4, onde w*h é a quantidade de pixels e o 4 vem do fato de que cada pixel é composto de 4 canais: red, green, blue e alpha – transparência.
Tentando exemplificar um pouco, a estrutura do array é:
[componente red do pixel 1,
componente green do pixel 1,
componente blue do pixel 1,
componente alpha do pixel 1,
componente red do pixel 2,
componente green do pixel 2,
componente blue do pixel 2,
componente alpha do pixel 2,
componente red do pixel 3,
componente green do pixel 3,
...]
Onde o valor de cada componente varia de 0 à 255.
Ou seja, se, e somente se, seu canvas tiver 300px de largura, sua primeira linha será representada pelos pixels de 0 -red do 1o pixel – até 1200 – alpha do 300o pixel.
Então para colocar o pixel do meio da 2a linha como verde o código seria: arrPix[1801]=255;arrPix[1803]=255; .
Onde arrPix[1801] é a componente verde do pixel que se inicia em 1800; e
arrPix[1803] é a transparência do mesmo onde o 255 é o sólido sem transparência.
Depois de tudo devemos utilizar a instrução abaixo para atualizar o canvas:
context.putImageData(imgd, 0,0); //cria a imagem na posição 0,0 do canvas.
Convenhamos: É possível trabalhar assim. Mas não é nada prático.
Então criei a classe abaixo chamada bitMapCanvas para facilitar a nossa vida:
function bitMapCanvas(psIdCanvas)
{
this.cnv; //canvas
this.ctx; //context
this.img; //imagem
this.w;
this.h;
//obtem objeto canvas
this.cnv = document.getElementById(psIdCanvas);
//obtem o contexto 2d
this.ctx = this.cnv.getContext('2d');
//pega os valores de altura e largura do canvas
this.w=parseInt(this.cnv.width);
this.h=parseInt(this.cnv.height);
//cria ou obtem o array de pixels
if (this.ctx.createImageData) {
this.img = this.ctx.createImageData(this.w, this.h);
} else if (this.ctx.getImageData) {
this.img = this.ctx.getImageData(0, 0, this.w, this.h);
} else {
this.img = {'width' : this.w,
'height' :this.h,
'data' : new Array(this.w*this.h*4)};
}
this.setPixel=function(piLeft, piTop, piRed, piGreen, piBlue, piAlpha)
{
iPixel=piTop*this.w*4+(piLeft*4);
this.img.data[iPixel]=piRed;
this.img.data[iPixel+1]=piGreen;
this.img.data[iPixel+2]=piBlue;
this.img.data[iPixel+3]=piAlpha;
this.ctx.putImageData(this.img, 0,0);
}
this.getPixel=function(piLeft, piTop)
{
iPixel=piTop*this.w*4+(piLeft*4);
return [this.img.data[iPixel],
this.img.data[iPixel+1],
this.img.data[iPixel+2],
this.img.data[iPixel+3]];
}
this.clear=function()
{
this.img = {'width' : this.w,
'height' :this.h,
'data' : new Array(this.w*this.h*4)};
this.ctx.putImageData(this.img, 0,0);
}
this.getContext=function()
{
return this.ctx;
}
}
Dado um elemento html canvas de id=arena de width=”300px” e height=”300px”, segue a demonstração de como utilizar o bitMapCanvas:
//obtem um novo bitMapCanvas ligado ao canvas arena.
G_bcvArena = new bitMapCanvas('arena');
//desenha o famigerado pixel verde no centro do canvas
G_bcvArena.setPixel(150,150,0,255,0,255);
//Querendo desenhar outras formas basta obter o contexto e utiliza-lo normalmente.
ctx = G_bcvArena.getContext();
//Como nem sempre é simples encontrar um pixel isolado na tela,
//desenharemos um círculo em volta do mesmo
ctx.beginPath();
ctx.arc(150, 150, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.stroke();
E é isso! Abraços e até a próxima!
Este post foi postado quinta-feira, 27 de janeiro de 2011 às 8:35 e está em Programação. Você pode verificar qualquer resposta a este post através do feed RSS 2.0.
Você pode deixar uma resposta, ou fazer um trackback de seu próprio site.
26 de fevereiro de 2011 às 7:11
[...] desta moto e que elas viram sempre num ângulo de 90o. Aproveitando a biblioteca criada no post Canvas: Manipulação Pixel a Pixel “Pixel Based” em Javascript, criei este pequeno jogo que ilustra o funcionamento da biblioteca. Então este jogo é para você [...]