Cómo sacar el componente ARGB de BitmapContext en el iPhone?
Pregunta
Estoy tratando de obtener componentes ARGB de CGBitmapContext con los siguientes códigos:
-(id) initWithImage: (UIImage*) image //create BitmapContext with UIImage and use 'pixelData' as the pointer
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (image.size.width * 4);
bitmapByteCount = (bitmapBytesPerRow * image.size.height);
colorSpace = CGColorSpaceCreateDeviceRGB();
pixelData = malloc( bitmapByteCount ); //unsigned char* pixelData is defined in head file
context = CGBitmapContextCreate (pixelData,
image.size.width,
image.size.height,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst
);
CGColorSpaceRelease( colorSpace );
CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
pixelData = CGBitmapContextGetData(context);
return self;
}
-(float) alphaAtX:(int)x y:(int)y //get alpha component using the pointer 'pixelData'
{
return pixelData[(y *width + x) *4 + 3]; //+0 for red, +1 for green, +2 for blue, +3 for alpha
}
-(void)viewDidLoad {
[super viewDidLoad];
UIImage *img = [UIImage imageNamed:@"MacDrive.png"]; //load image
[self initWithImage:img]; //create BitmapContext with UIImage
float alpha = [self alphaAtX:20 y:20]; //store alpha component
}
Cuando intento para almacenar rojo / verde / azul, que resultan ser siempre 240. Y alfa es siempre 255.
Así que creo que tal vez algo está mal con el puntero. No podría devolver los datos correctos ARGB que quiero. Alguna idea acerca de lo que está mal con el código?
Solución
En primer lugar, usted está perdiendo memoria, la memoria pixelData nunca se liberó.
Para su uso, es mejor dejar que las llamadas CGContext gestionar la memoria. Basta con pasar i.s.o. NULL pixelData, y siempre y cuando mantenga el recuento de referencia arriba en su contexto, el CGBitmapContextGetData(context)
seguirá siendo válida.
Usted está utilizando alfa como si fuera la última entrada (RGBA, no ARGB), usarlo como tal en la creación de su contexto, o adaptar el código alphaAtX
. No estoy seguro de si quieres premultiplicado, si es sólo para comprobar valores alfa, no lo hace.
Con todo algo como:
[...]
CGContextRelease(context);
context = CGBitmapContextCreate (NULL,
image.size.width,
image.size.height,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaLast
);
CGColorSpaceRelease( colorSpace );
CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
pixelData = CGBitmapContextGetData(context);
[...]
con ser contexto una variable miembro, inicializado a NULL, ya habrá un paso en la dirección correcta.
Otros consejos
En primer lugar, me gustaría comprobar para ver si el contexto regresó de su llamada CGBitmapContextCreate
es válido (es decir, asegurarse de context != NULL
). También me gustaría comprobar para asegurarse de que su imagen cargada originalmente es válido (es así, asegúrese de que img != nil
).
Si el contexto es nula, puede ser debido a que su tamaño de la imagen no es razonable, o bien su formato de datos de píxel no está disponible. Trate de usar kCGImageAlphaPremultipliedLast
lugar?
En segundo lugar, no es necesario utilizar CGBitmapContextGetData
- sólo puede utilizar el puntero pixelData
que ha pasado en el primer lugar. También debe CGContextRelease
su contexto antes de salir de su función initWithImage:
para evitar una fuga.
También observo que está utilizando kCGImageAlphaPremultipliedFirst
. Esto significa que el componente alfa es primero , no dura, en su imagen, por lo que desea un desplazamiento de 0 para el componente alfa en su función alphaAtX:y:
.
¿Alguno de esa ayuda?