Manipulación de píxeles

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

La clase BitmapData contiene un conjunto de métodos que permiten manipular los valores de los datos de los píxeles.

Manipulación de píxeles individuales

Cuando se desea cambiar la apariencia de una imagen de mapa de bits a nivel de sus píxeles, en primer lugar es necesario obtener los valores de color de los píxeles que contiene el área que se pretende manipular. Para leer esos valores de los píxeles se utiliza el método getPixel() .

El método getPixel() obtiene el valor RGB del par de coordenadas x, y (píxel) que se le pasan como parámetros. Si alguno de los píxeles que se desea manipular incluye información de transparencia (canal alfa), será necesario emplear el método getPixel32() . Este método también lee un valor RGB pero, al contrario que getPixel() , el valor devuelto por getPixel32() contiene datos adicionales que representan el valor del canal alfa (transparencia) del píxel seleccionado.

Por otra parte, si simplemente se desea cambiar el color o la transparencia de un píxel que pertenece a un mapa de bits, se pueden usar los métodos setPixel() o setPixel32() . Para definir el color de un píxel basta con pasar las coordenadas x, y, además del valor del color, a uno de estos métodos.

En el siguiente ejemplo se utiliza setPixel() para dibujar una cruz en un fondo BitmapData verde. A continuación, se emplea getPixel() para leer el valor del color del píxel que se encuentra en las coordenadas 50, 50 y se realiza un seguimiento del valor devuelto.

import flash.display.Bitmap; 
import flash.display.BitmapData; 
 
var myBitmapData:BitmapData = new BitmapData(100, 100, false, 0x009900); 
 
for (var i:uint = 0; i < 100; i++) 
{ 
    var red:uint = 0xFF0000; 
    myBitmapData.setPixel(50, i, red); 
    myBitmapData.setPixel(i, 50, red); 
} 
 
var myBitmapImage:Bitmap = new Bitmap(myBitmapData); 
addChild(myBitmapImage); 
 
var pixelValue:uint = myBitmapData.getPixel(50, 50); 
trace(pixelValue.toString(16));

Si se desea leer el valor de un grupo de píxeles, en lugar del de uno solo, se debe usar el método getPixels() . Este método genera un conjunto de bytes a partir de una región rectangular de datos de píxeles que se transmite como parámetro. Cada uno de los elementos del conjunto de bytes (dicho de otro modo, los valores de los píxeles) es un entero sin signo, es decir, un valor de píxel no multiplicado de 32 bits.

A la inversa, para cambiar (o definir) el valor de un grupo de píxeles, se usa el método setPixels() . Este método recibe dos parámetros ( rect y inputByteArray ), que se combinan para dar lugar a una región rectangular ( rect ) de datos de píxeles ( inputByteArray ).

A medida que se leen (y escriben) los datos de inputByteArray , se llama al método ByteArray.readUnsignedInt() para cada uno de los píxeles del conjunto. Si, por algún motivo, inputByteArray no contiene todo un rectángulo de datos de píxeles, el método deja de procesar los datos de imagen en ese punto.

Es importante recordar que, tanto para leer como para definir los datos de los píxeles, el conjunto de bytes espera valores de píxeles de 32 bits compuestos por los canales alfa, rojo, verde y azul (ARGB).

En el siguiente ejemplo se utilizan los métodos getPixels() y setPixels() para copiar un grupo de píxeles de un objeto BitmapData a otro:

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.utils.ByteArray; 
import flash.geom.Rectangle; 
 
var bitmapDataObject1:BitmapData = new BitmapData(100, 100, false, 0x006666FF); 
var bitmapDataObject2:BitmapData = new BitmapData(100, 100, false, 0x00FF0000); 
 
var rect:Rectangle = new Rectangle(0, 0, 100, 100); 
var bytes:ByteArray = bitmapDataObject1.getPixels(rect); 
 
bytes.position = 0; 
bitmapDataObject2.setPixels(rect, bytes); 
 
var bitmapImage1:Bitmap = new Bitmap(bitmapDataObject1); 
addChild(bitmapImage1); 
var bitmapImage2:Bitmap = new Bitmap(bitmapDataObject2); 
addChild(bitmapImage2); 
bitmapImage2.x = 110;

Detección de colisiones a nivel de píxeles

El método BitmapData.hitTest() lleva a cabo una detección de colisiones a nivel de píxeles entre los datos de un mapa de bits y otro objeto o punto.

El método BitmapData.hitTest() acepta cinco parámetros:

  • firstPoint (Point): este parámetro hace referencia a la posición del píxel de la esquina superior izquierda del primer objeto BitmapData sobre el que se realizará la comprobación de colisiones.

  • firstAlphaThreshold (uint): este parámetro especifica el valor de canal alfa más alto que se considera opaco para esta prueba.

  • secondObject (objeto): este parámetro representa el área de impacto. El objeto secondObject puede ser un objeto Rectangle, Point, Bitmap o BitmapData. Este objeto representa el área de impacto sobre la que se realizará la detección de colisiones.

  • secondBitmapDataPoint (Point): este parámetro opcional se utiliza para definir la posición de un píxel en el segundo objeto BitmapData. y solo se utiliza cuando el valor de secondObject es un objeto BitmapData. El valor predeterminado es null .

  • secondAlphaThreshold (uint): este parámetro opcional representa el valor de canal alfa más alto que se considera opaco en el segundo objeto BitmapData. El valor predeterminado es 1. Este parámetro solo se utiliza cuando el valor de secondObject es un objeto BitmapData y los dos objetos BitmapData son transparentes.

Al llevar a cabo la detección de colisiones sobre imágenes opacas, es conveniente recordar que ActionScript trata la imagen como si fuera un rectángulo (o recuadro delimitador) totalmente opaco. Por otra parte, al realizar la prueba de impactos a nivel de píxeles en imágenes transparentes, es necesario que las dos imágenes sean transparentes. Además, ActionScript utiliza los parámetros de umbral alfa para determinar en qué punto los píxeles pasan de ser transparentes a opacos.

En el siguiente ejemplo se crean tres imágenes de mapa de bits y se realiza una detección de colisiones de píxeles utilizando dos puntos de colisión distintos (uno devuelve false y el otro true):

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.geom.Point; 
 
var bmd1:BitmapData = new BitmapData(100, 100, false, 0x000000FF); 
var bmd2:BitmapData = new BitmapData(20, 20, false, 0x00FF3300); 
 
var bm1:Bitmap = new Bitmap(bmd1); 
this.addChild(bm1); 
 
// Create a red square. 
var redSquare1:Bitmap = new Bitmap(bmd2); 
this.addChild(redSquare1); 
redSquare1.x = 0; 
 
// Create a second red square. 
var redSquare2:Bitmap = new Bitmap(bmd2); 
this.addChild(redSquare2); 
redSquare2.x = 150; 
redSquare2.y = 150; 
 
// Define the point at the top-left corner of the bitmap. 
var pt1:Point = new Point(0, 0); 
// Define the point at the center of redSquare1. 
var pt2:Point = new Point(20, 20); 
// Define the point at the center of redSquare2. 
var pt3:Point = new Point(160, 160); 
 
trace(bmd1.hitTest(pt1, 0xFF, pt2)); // true 
trace(bmd1.hitTest(pt1, 0xFF, pt3)); // false