У меня есть UIView
, который я хочу сохранить как UIImage
. Я делаю это с помощью UIGraphicsBeginImageContext
, и он работает нормально. Но когда я применяю маску к изображениям в (view/layer.mask), изображение, которое я захватываю через UIGraphicsBeginImageContext
, ошибочно (маскирование работает при запуске приложения, но не при попытке получить UIImage
из UIView
). Кто-нибудь сталкивался с подобной проблемой?
Маска не работает при захвате uiview для uiimage
Ответ 1
Если я правильно понимаю, вы хотите создать UIImage из слоя UIView, в то время как этот слой замаскирован. Я предполагаю, что вы хотите, чтобы целевой UIImage имел прозрачный фон.
У меня не было проблем с этим, и у меня есть демонстрационный проект, на который вы можете взглянуть:
https://bitbucket.org/reydan/so_imagemask
Сначала вам нужно нажать кнопку Маска. Он загрузит изображение маски (черно-белое) из пакета и установит его как маску слоя для контейнера UIView выше.
Затем вы можете нажать кнопку Копировать изображение, которая отображает контейнер UIView в UIImage, а затем установите его в изображение целевого изображения ниже, чтобы увидеть результат.
Я также опубликую здесь 2 метода:
- (IBAction)onMask:(id)sender {
UIImage* maskImage = [UIImage imageNamed:@"star.png"];
UIImageView* maskImageView = [[UIImageView alloc] initWithImage:maskImage];
maskImageView.contentMode = UIViewContentModeScaleAspectFit;
maskImageView.frame = _mainContainerView.bounds;
_mainContainerView.layer.mask = maskImageView.layer;
}
- (IBAction)onCopyImage:(id)sender {
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, FALSE, [[UIScreen mainScreen] scale]);
[_mainContainerView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_destImageView.image = img;
}
ИЗМЕНИТЬ
По-видимому, renderInContext:
на IOS6 не использует маску (как сказано здесь и на SO).
Мое решение состояло в том, чтобы вручную применить маску к изображению. Маска берется из свойства маски слоя и визуализируется в контексте, поэтому у нас нет проблем с преобразованиями /contentModes/etc.
Вот обновленный исходный код (он также доступен на битбакете):
- (IBAction)onCopyImage:(id)sender {
// Get the image from the mainImageView
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, FALSE, [[UIScreen mainScreen] scale]);
[_mainContainerView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Use the next block if targeting IOS6
{
// Manually create a mask image (taken from the mask layer)
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, TRUE, [[UIScreen mainScreen] scale]);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextFillRect(ctx, _mainContainerView.bounds);
[_mainContainerView.layer.mask renderInContext:ctx];
UIImage * maskimg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create a image mask from the UIImage
CGImageRef maskRef = maskimg.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
// Apply the mask to our source image
CGImageRef maskedimg= CGImageCreateWithMask(img.CGImage, mask);
// Convert to UIImage so we can easily display it in a UIImageView
img = [UIImage imageWithCGImage:maskedimg scale:img.scale orientation:img.imageOrientation];
CGImageRelease(mask);
CGImageRelease(maskedimg);
}
_destImageView.image = img;
}
ИЗМЕНИТЬ Пожалуйста, проверьте последний проект на битбакете, поскольку он содержит последнюю версию.
Ответ 2
Вот пример кода, который я использовал для получения UIView как изображения UIImageView и Apply mask для этого.
* UIView --> UIImageView --> With Mask images .
Я использовал UIView для рисования для этого,
Назначение UIView (рисованной области) в UIImageView.
-(UIImage*) imageRepresentation
{
[EAGLContext setCurrentContext:context];
UIImageView* upsideDownImageView=[[UIImageView alloc] initWithImage: [self upsideDownImageRepresenation]];
upsideDownImageView.transform=CGAffineTransformScale(upsideDownImageView.transform, 1, -1);
UIView* container=[[UIView alloc] initWithFrame:upsideDownImageView.frame];
[container addSubview:upsideDownImageView];
UIImage* toReturn=nil;
UIGraphicsBeginImageContext(container.frame.size);
[container.layer renderInContext:UIGraphicsGetCurrentContext()];
toReturn = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//[upsideDownImageView release];
upsideDownImageView = nil;
container = nil;
//[container release];
return toReturn;
}
-(UIImage*) upsideDownImageRepresenation
{
int imageWidth = CGRectGetWidth([self bounds]);
int imageHeight = CGRectGetHeight([self bounds]);
//image buffer for export
NSInteger myDataLength = imageWidth* imageHeight * 4;
// allocate array and read pixels into it.
GLubyte *tempImagebuffer = (GLubyte *) malloc(myDataLength);
glReadPixels( 0, 0, imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, tempImagebuffer);
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, tempImagebuffer, myDataLength, ProviderReleaseData);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * imageWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef] ;
CGDataProviderRelease(provider);
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
return myImage;
}
Теперь у вас есть представление UIImageView UIView.
Теперь давайте сделаем это с эффектом маски.
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0); //imageView is wt we got by converting the UIIVew.
[self.imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
// Add the mask Images even if want any UILabels etc ..
[imageView.image drawInRect:CGRectMake(0, 0, 703, 315)];
[maskImages.image drawAtPoint:CGPointMake(10, 10) blendMode:kCGBlendModeNormal alpha:0.2];
[lblAckNo drawTextInRect:CGRectMake(320, 230,100,50)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();// image with all of your effort.
[[UIColor redColor] set];
UIGraphicsEndImageContext();