我可以在 UIImageView 中编辑 UIImage 的 Alpha Mask,而不必移动太多内存吗?

发布于 2024-11-03 23:45:11 字数 318 浏览 6 评论 0原文

我想拍摄一个图像(画笔)并将其绘制到显示的图像中。我只想影响该图像的 Alpha,并且需要稍后将其导出。

据我所知,大多数方向实际上只是进行了一些看起来成本高昂但不会成功的操作。即,他们建议您绘制到屏幕外上下文中,创建遮罩的 CGImage,并在每次应用画笔时创建 CGImageWithMask。

我已经知道这代价高昂,因为对于 iPhone 来说,即使只是这样做并绘制到上下文中也是相当粗糙的。

我想做的是获取 UIImageView 的 UIImage,并直接操作它的 Alpha 通道。我也不是逐个像素地进行操作,而是使用具有自身柔软度的较大(20px 半径)画笔。

I want to take a image (a brush) and draw it into a displayed image. I only want to affect the alpha of that image, and I need to export it later.

From what I've seen, most directions only really get into some costly looking operations that don't pan out. ie they recommend you draw into an offscreen context, create a CGImage of the mask, and create a CGImageWithMask pretty much every time the brush is applied at all.

I already know this is costly because even just doing this and drawing into a context is rather rough for iPhone.

What I'd like to do is take the UIImage of an UIImageView, and manipulate it's alpha channel directly. I also am not doing it pixel-by-pixel, but with a largish (20px radius) brush that has a softness of its own.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云柯 2024-11-10 23:45:11

我不会为此使用 UIImageView。一个普通的 UIView 就足够了。

只需将图像放入图层中,

UIView *view = ...
view.layer.contents = (id)image.CGImage;

然后您可以通过向图层添加蒙版

CALayer *mask = [[CALayer alloc] init]
mask.contents = maskimage.CGImage;
view.layer.mask = mask;

来使图像的某些部分透明,我做了一个项目,其中我有一个 Brush.png,您可以用它来用手指显示图像。 ..我的更新掩码功能是:

- (void)updateMask {

    const CGSize size = self.bounds.size;
    const size_t bitsPerComponent = 8;
    const size_t bytesPerRow = size.width; //1byte per pixel
    BOOL freshData = NO;
    if(NULL == _maskData || !CGSizeEqualToSize(size, _maskSize)) {
        _maskData = calloc(sizeof(char), bytesPerRow * size.height);
        _maskSize = size;
        freshData = YES;
    }

    //release the ref to the bitmat context so it doesn't get copied when we manipulate it later
    _maskLayer.contents = nil;
    //create a context to draw into the mask
    CGContextRef context = 
    CGBitmapContextCreate(_maskData, size.width, size.height, 
                          bitsPerComponent, bytesPerRow,
                          NULL,
                          kCGImageAlphaOnly);
    if(NULL == context) {
        LogDebug(@"Could not create the context");
        return;
    }

    if(freshData) {
        //fill with mask with alpha == 0, which means nothing gets revealed
        CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));    
    }

    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);

    //Draw all the points in the array into a mask
    for (NSValue* pointValue in _pointsToDraw)
    {
        CGPoint point;
        [pointValue getValue:&point];
        //LogDebug(@"location: %@", NSStringFromCGPoint(point));

        [self drawBrush:[_brush CGImage] at:point inContext:context];
    }
    [_pointsToDraw removeAllObjects];

    //extract an image from it
    CGImageRef newMask = CGBitmapContextCreateImage(context);

    //release the context
    CGContextRelease(context);

    //now update the mask layer
    _maskLayer.contents = (id)newMask;
    //self.layer.contents = (id)newMask;
    //and release the mask as it's retained by the layer
    CGImageRelease(newMask);
}

I would not use an UIImageView for this. A normal UIView is enough.

Just put the Image into the layer with

UIView *view = ...
view.layer.contents = (id)image.CGImage;

after that you can make parts of the image transparent by adding a mask to the layer

CALayer *mask = [[CALayer alloc] init]
mask.contents = maskimage.CGImage;
view.layer.mask = mask;

for a project I did something where I had a brush.png that you could use to reveal an image with a finger... my update mask function there was:

- (void)updateMask {

    const CGSize size = self.bounds.size;
    const size_t bitsPerComponent = 8;
    const size_t bytesPerRow = size.width; //1byte per pixel
    BOOL freshData = NO;
    if(NULL == _maskData || !CGSizeEqualToSize(size, _maskSize)) {
        _maskData = calloc(sizeof(char), bytesPerRow * size.height);
        _maskSize = size;
        freshData = YES;
    }

    //release the ref to the bitmat context so it doesn't get copied when we manipulate it later
    _maskLayer.contents = nil;
    //create a context to draw into the mask
    CGContextRef context = 
    CGBitmapContextCreate(_maskData, size.width, size.height, 
                          bitsPerComponent, bytesPerRow,
                          NULL,
                          kCGImageAlphaOnly);
    if(NULL == context) {
        LogDebug(@"Could not create the context");
        return;
    }

    if(freshData) {
        //fill with mask with alpha == 0, which means nothing gets revealed
        CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));    
    }

    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);

    //Draw all the points in the array into a mask
    for (NSValue* pointValue in _pointsToDraw)
    {
        CGPoint point;
        [pointValue getValue:&point];
        //LogDebug(@"location: %@", NSStringFromCGPoint(point));

        [self drawBrush:[_brush CGImage] at:point inContext:context];
    }
    [_pointsToDraw removeAllObjects];

    //extract an image from it
    CGImageRef newMask = CGBitmapContextCreateImage(context);

    //release the context
    CGContextRelease(context);

    //now update the mask layer
    _maskLayer.contents = (id)newMask;
    //self.layer.contents = (id)newMask;
    //and release the mask as it's retained by the layer
    CGImageRelease(newMask);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文