Wie die ARGB-Komponente aus BitmapContext auf iPhone herausziehen zu?
Frage
Ich versuche ARGB Komponenten aus CGBitmapContext mit folgenden Codes zu bekommen:
-(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
}
Wenn ich versuche, rot / grün / blau zu speichern, sie erweisen sich als immer 240. Und Alpha ist immer 255.
So denke ich, vielleicht ist etwas falsch mit dem Zeiger. Es kann nicht die richtigen ARGB Daten zurückgeben ich will. Irgendwelche Ideen, was ist los mit dem Code?
Lösung
Zu allererst Sie undichte Speicher, der Pixeldata Speicher wird nie freigegeben.
Für Ihre Nutzung ist es besser, die CGContext Anrufe die Speicher verwalten zu lassen. Übergeben Sie einfach NULL I.S.O. Pixeldata, und solange Sie die Referenz auf Ihrem Kontext zählen zu halten, wird die CGBitmapContextGetData(context)
gültig bleiben.
Sie alpha verwenden, als ob es der letzte Eintrag (RGBA, nicht ARGB) wurde, es als solches in der Erstellung Ihrer Kontext verwenden oder den alphaAtX
Code anzupassen. Ich bin mir nicht sicher, ob Sie premultiplied wollen, wenn es nur Alpha-Werte zu überprüfen, können Sie dies nicht tun.
Alles in allem so etwas wie:
[...]
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);
[...]
mit Kontext eine Membervariable ist, auf NULL initialisiert, wird bereits ein Schritt in der richtigen Richtung sein.
Andere Tipps
Als erstes würde ich überprüfen, um zu sehen, ob der Zusammenhang von Ihrem CGBitmapContextCreate
Aufruf zurückgegeben gültig ist (das heißt, stellen Sie sicher, context != NULL
). Ich würde überprüfen, um auch sicherstellen, dass Ihr ursprünglich geladene Bild gültig ist (so stellen Sie sicher, img != nil
).
Wenn Ihr Kontext null ist, kann es sein, weil Sie Ihre Bildgröße nicht vertretbar ist, oder auch Ihr Pixeldatenformat ist nicht verfügbar. Versuchen Sie es mit kCGImageAlphaPremultipliedLast
statt?
Zweitens brauchen Sie nicht CGBitmapContextGetData
verwenden - man muss nur den pixelData
Zeiger Sie an erster Stelle geführt verwenden kann. Sie sollten Ihre CGContextRelease
Funktion vor dem Verlassen ein Leck zu vermeiden.
initWithImage:
Ihren Kontext auch
Ich stelle auch fest, dass Sie kCGImageAlphaPremultipliedFirst
verwenden. Dies bedeutet, dass die Alpha-Komponente ist zuerst , nicht zuletzt, in Ihrem Bild, so dass Sie ein 0 für die Alpha-Komponente in Ihrer alphaAtX:y:
Funktion versetzt werden sollen.
Gibt es irgendeine dieser Hilfe?