【问题标题】:Mask does not work when capturing a uiview to a uiimage将 uiview 捕获到 uiimage 时,掩码不起作用
【发布时间】:2012-12-04 08:19:52
【问题描述】:

我有一个UIView,我想将它保存为UIImage。我使用UIGraphicsBeginImageContext 执行此操作,它工作正常。但是当我对 (view/layer.mask) 中的图像应用蒙版时,我通过 UIGraphicsBeginImageContext 捕获的图像是错误的(运行应用程序时蒙版有效,但在尝试从UIView)。有人遇到过类似的问题吗?

【问题讨论】:

  • 您能否提供一些代码来显示您目前拥有的内容?
  • 您是否在从中捕获 UIImage 之前屏蔽源 UIView?还是您在尝试在 UIImageView 中显示结果时屏蔽了结果 UIImage?
  • 我添加了一些示例代码。
  • 没有示例代码
  • 屏蔽代码:UIImage *_maskingImage = self.maskImage; CALayer *_maskingLayer = [CALayer layer]; _maskingLayer.frame = self.bounds; [_maskingLayer setContents:(id)[_maskingImage CGImage]]; [self.layer setMask:_maskingLayer];

标签: ios uiview uiimage calayer mask


【解决方案1】:

如果我理解正确,您希望从 UIView 层创建 UIImage,而该层被屏蔽。我假设您希望目标 UIImage 具有透明背景。

我没有遇到任何问题,我有一个演示项目,你可以看看:

https://bitbucket.org/reydan/so_imagemask

您首先需要按蒙版按钮。它将从包中加载一个遮罩图像(黑白)并将其设置为上面 UIView 容器的图层遮罩。

然后,你可以点击Copy Image按钮,将UIView容器渲染成一个UIImage,然后将其设置到下面的目标图像视图中查看结果。

我也会在这里发布这两种方法:

- (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;
}

编辑

显然 IOS6 上的 renderInContext: 不使用掩码(正如这里所说的那样)。 我的解决方案是手动将蒙版应用于图像。蒙版取自图层的蒙版属性并在上下文中渲染,因此我们在转换/内容模式/等方面没有任何问题。

这是更新后的源代码(也可以在 bitbucket 上找到):

- (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;

}

编辑 请检查 bitbucket 上的最新项目,因为它包含最新版本。

【讨论】:

  • 这对我不起作用。我仍然在 UIImage 中得到平方的 UIView。我使用与您完全相同的代码。我不明白???您的示例项目为我工作。它可以是 iOS 7 SDK 的东西吗?你的项目是在 iOS 7 中构建的,而我的项目是在 iOS 6 中构建的。这有什么不同吗?
  • 我会尝试使用 ios 6 并返回答案
  • 确实,它不适用于 ios 6.1 我没想到会这样。我将如何更新项目以使其正常工作。
  • 我添加了一个新的解决方案,它使用更少的内存,但掩码图像被反转(因为 CGImageCreateWithMask 的工作方式)。它也可以在 bitbucket 上找到。
  • 抱歉,在我的项目中,我有多个蒙面 UIView。你有什么解决办法吗?
【解决方案2】:

这里是一些示例代码,我用它来获取 UIView 作为 UIImageView 并为此应用蒙版图像。

 * 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;
}

现在您有了 UIView 的 UIImageView 表示。

现在让我们用蒙版效果来制作它。

 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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    相关资源
    最近更新 更多