Come estrarre il componente ARGB da BitmapContext su iPhone?
Domanda
Sto cercando di ottenere componenti ARGB da CGBitmapContext con i seguenti codici:
-(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 nomeimmagine:@"MacDrive.png"];//carica l'immagine
[self initWithImage:img]; //create BitmapContext with UIImage
float alpha = [self alphaAtX:20 y:20]; //store alpha component
}
Quando provo a memorizzare rosso/verde/blu, risultano sempre 240.E l'alfa è sempre 255.
Quindi penso che forse c'è qualcosa che non va nel puntatore.Non è stato possibile restituire i dati ARGB corretti che desidero.Qualche idea su cosa c'è che non va nel codice?
Soluzione
Prima di tutto, si sta perdendo la memoria, la memoria pixelData non viene mai liberato.
Per l'utilizzo, è meglio lasciare che le chiamate CGContext gestire la memoria. È sufficiente passare i.s.o. NULL pixelData, e finché si mantiene il conteggio di riferimento sul vostro contesto, il CGBitmapContextGetData(context)
rimarrà valido.
Si sta utilizzando alfa come se fosse l'ultima voce (RGBA, non ARGB), usarlo come tale nella creazione del vostro contesto, o adattare il codice alphaAtX
. Non sono sicuro se si vuole premoltiplicato, se è solo per controllare i valori alfa, non lo fai.
Tutto sommato qualcosa di simile:
[...]
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 contesto essendo un membro variabile inizializzata NULL, sarà già un passo nella direzione giusta.
Altri suggerimenti
Innanzitutto, controllerei per vedere se il contesto restituito da your CGBitmapContextCreate
la chiamata sia valida (ovvero, assicurati context != NULL
).Vorrei anche verificare che l'immagine caricata originariamente sia valida (quindi assicurati img != nil
).
Se il tuo contesto è pari a zero, è possibile che la dimensione dell'immagine sia irragionevole oppure che il formato dei dati in pixel non sia disponibile.Prova a utilizzare kCGImageAlphaPremultipliedLast
Invece?
In secondo luogo, non è necessario utilizzarlo CGBitmapContextGetData
- puoi semplicemente usare il file pixelData
puntatore che hai passato in primo luogo.Dovresti anche CGContextRelease
il tuo contesto prima di lasciare il tuo initWithImage:
funzione per evitare perdite.
Noto anche che stai utilizzando kCGImageAlphaPremultipliedFirst
.Ciò significa che la componente alfa lo è Primo, non ultimo, nella tua immagine, quindi vuoi un offset pari a 0 per il componente alfa nel tuo alphaAtX:y:
funzione.
Tutto ciò aiuta?