Как вытащить компонент ARGB из BitmapContext на iPhone?
Вопрос
Я пытаюсь получить компоненты ARGB из CGBitmapContext с помощью следующих кодов:
-(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"];//загружаем изображение
[self initWithImage:img]; //create BitmapContext with UIImage
float alpha = [self alphaAtX:20 y:20]; //store alpha component
}
Когда я пытаюсь сохранить красный/зеленый/синий, их всегда оказывается 240.А альфа всегда 255.
Вот я и думаю, что с указателем что-то не так.Он не смог вернуть правильные данные ARGB, которые мне нужны.Есть идеи, что не так с кодом?
Решение
Прежде всего, у вас происходит утечка памяти, память PixelData никогда не освобождается.
Для вашего использования лучше позволить вызовам CGContext управлять памятью.Просто передайте NULL i.s.o.PixelData, и пока вы поддерживаете подсчет ссылок в вашем контексте, CGBitmapContextGetData(context)
останется в силе.
Вы используете альфу, как если бы это была последняя запись (RGBA, а не ARGB), используйте ее как таковую при создании контекста или адаптируйте alphaAtX
код.Я не уверен, хотите ли вы предварительно умножить, если это просто проверка альфа-значений, то нет.
В целом что-то вроде:
[...]
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);
[...]
если контекст является переменной-членом, инициализированной значением NULL, это уже будет шагом в правильном направлении.
Другие советы
Во-первых, я бы проверил, вернулся ли контекст из вашего CGBitmapContextCreate
вызов действителен (то есть убедитесь, что context != NULL
).Я бы также проверил, действительно ли ваше первоначально загруженное изображение (поэтому убедитесь, что img != nil
).
Если ваш контекст равен нулю, это может быть связано с необоснованным размером вашего изображения или с тем, что формат ваших пиксельных данных недоступен.Попробуйте использовать kCGImageAlphaPremultipliedLast
вместо?
Во-вторых, вам не нужно использовать CGBitmapContextGetData
- вы можете просто использовать pixelData
указатель, который вы передали в первую очередь.Вам также следует CGContextRelease
ваш контекст, прежде чем покинуть свой initWithImage:
Функция предотвращения утечки.
Я также отмечаю, что вы используете kCGImageAlphaPremultipliedFirst
.Это означает, что альфа-компонент первый, а не последним, в вашем изображении, поэтому вам нужно смещение 0 для альфа-компонента в вашем alphaAtX:y:
функция.
Что-нибудь из этого помогает?