Получить передний план от AdobeLabsUXMagicSelectionView (Adobe Creative SDK)
Я пытаюсь использовать AdobeLabsUXMagicSelectionView и сталкиваюсь с двумя проблемами. Я хочу "вырезать" выделенную область (передний план), используя эти 2 метода:
Способ 1) getForeground:andMatte:
Это не дает мне правильный передний план. Когда я выбираю область и звоню getForeground:andMatte
Я даю мне передний план и задний план (смешанный).
Документация гласит:
В качестве альтернативы, если вам не нужно напрямую обрабатывать базовое растровое изображение и намереваться использовать результаты в качестве входных данных для CoreGraphics или CoreImage, вы можете вызвать:
Способ 2) После этого я пытаюсь "вырезать", как это делает документация
extension AdobeLabsUXMagicSelectionView {
func foregroundCGImage() -> CGImage {
let w = size_t(self.image.size.width)
let h = size_t(self.image.size.height)
let data = UnsafeMutablePointer<UInt8>(malloc(4 * w * h * sizeof(UInt8)))
self.readForegroundAndMatteIntoBuffer(data)
for var i = 0; i < 4 * w * h; i += 4 {
let alpha: UInt8 = UInt8(data[i + 3]) / 255
data[i] *= alpha
data[i + 1] *= alpha
data[i + 2] *= alpha
}
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipLast.rawValue)
let ctx = CGBitmapContextCreate(data, w, h, 8, 4 * w, CGColorSpaceCreateDeviceRGB(), bitmapInfo.rawValue)
let imageRef = CGBitmapContextCreateImage(ctx)!
return imageRef
}
}
Но он только закрашивает (черный) невыбранную часть (фон) изображения.
Кто-нибудь может помочь? Я хочу получить окончательное изображение выбранной области.
ОБНОВИТЬ:
Как сказал @DonWoodward, я создал эту категорию:
@implementation AdobeLabsUXMagicSelectionView (Foreground)
- (UIImage *)getForeground {
// show the results
// first create a UIImage of just the foreground bits per the documentation in AdobeLabsUXMagicSelectionView.h
size_t w = self.image.size.width;
size_t h = self.image.size.height;
uint8_t *data = (uint8_t *)malloc(4*w*h*sizeof(uint8_t));
[self readForegroundAndMatteIntoBuffer:data];
// Paint the non-selected portion of the image black
for (int i = 0; i < 4*w*h; i += 4) {
float alpha = (float)data[i + 3] / 255;
data[i ] *= alpha;
data[i + 1] *= alpha;
data[i + 2] *= alpha;
}
CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return foregroundBits;
}
@end
Но результат имеет много черного пикселя вокруг "переднего плана".
Что мне нужно? Получить "чистый" передний план (выделенная область без черных пикселей), чтобы поместить поверх UIImageView
2 ответа
В этом случае вы предварительно умножаете каналы RGB на ваш альфа-канал, что подразумевает, что вы захотите использовать kCGImageAlphaPremultipliedLast
при создании вашего контекста, как в:
// Paint the non-selected portion of the image black
for (int i = 0; i < 4*w*h; i += 4)
{
float alpha = (float)data[i + 3] / 255;
data[i ] *= alpha;
data[i + 1] *= alpha;
data[i + 2] *= alpha;
}
CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
Более подробную информацию можно найти в документации CGImage
Кроме того, вы также можете попробовать использовать CGImageCreateWithMask
с выходом
- (void)getForeground:(UIImage **)foregroundImage andMatte:(UIImage **)matteImage
как описано в Руководстве по программированию Quartz 2D
UIImage *fg;
UIImage *matte;
[_magicSelectionView getForeground:&fg andMatte:&matte];
CGImageRef mattedForeground = CGImageCreateWithMask(fg.CGImage, matte.CGImage);
UIImage *foregroundBits = [UIImage imageWithCGImage:mattedForeground];
// show the results
_resultsView = [[UIImageView alloc] initWithFrame: CGRectMake(0, VIEW_Y_OFFSET, self.view.bounds.size.width, self.view.bounds.size.height-VIEW_Y_OFFSET)];
_resultsView.contentMode = UIViewContentModeScaleAspectFit;
[_resultsView setImage: foregroundBits];
[self.view addSubview: _resultsView];
Если ни один из этих способов не работает, возможно, возникли некоторые проблемы с настройкой UIImageViews
используется для визуализации результатов, но без этого кода трудно сказать.
Я думаю, что проблема в том, что ваш масштабный фактор имеет тип uint8_t
и поэтому вы обрезаете масштабный коэффициент до нуля. Сделайте это поплавком, и это должно работать. Вот код из MagicPuppy (в цели c), который делает это:
// show the results
// first create a UIImage of just the foreground bits per the documentation in AdobeLabsUXMagicSelectionView.h
size_t w = _magicSelectionView.image.size.width;
size_t h = _magicSelectionView.image.size.height;
uint8_t *data = (uint8_t *)malloc(4*w*h*sizeof(uint8_t));
[_magicSelectionView readForegroundAndMatteIntoBuffer:data];
// Paint the non-selected portion of the image black
for (int i = 0; i < 4*w*h; i += 4)
{
float alpha = (float)data[i + 3] / 255;
data[i ] *= alpha;
data[i + 1] *= alpha;
data[i + 2] *= alpha;
}
CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// show the results
_resultsView = [[UIImageView alloc] initWithFrame: CGRectMake(0, VIEW_Y_OFFSET, self.view.bounds.size.width, self.view.bounds.size.height-VIEW_Y_OFFSET)];
_resultsView.contentMode = UIViewContentModeScaleAspectFit;
[_resultsView setImage: foregroundBits];
[self.view addSubview: _resultsView];