ios 如何屏蔽 UIImageView?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5757386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:41:15  来源:igfitidea点击:

How can I mask a UIImageView?

iosobjective-cuiimagemask

提问by Mc.Lover

I am trying to mask an image with something like this:

我试图用这样的东西来掩盖图像:

image to be masked

要屏蔽的图像

Would you please help me?

你能帮我吗?

I am using this code:

我正在使用此代码:

- (void) viewDidLoad {
    UIImage *OrigImage = [UIImage imageNamed:@"dogs.png"];
    UIImage *mask = [UIImage imageNamed:@"mask.png"];
    UIImage *maskedImage = [self maskImage:OrigImage withMask:mask];
    myUIIMage.image = maskedImage;
}

回答by Bartosz Ciechanowski

There's an easier way.

有一个更简单的方法。

#import <QuartzCore/QuartzCore.h>
// remember to include Framework as well

CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, <img_width>, <img_height>);
yourImageView.layer.mask = mask;
yourImageView.layer.masksToBounds = YES;

For Swift 4 and plus follow code below

对于 Swift 4 及以上,请遵循以下代码

let mask = CALayer()
mask.contents =  [ UIImage(named: "right_challenge_bg")?.cgImage] as Any
mask.frame = CGRect(x: 0, y: 0, width: leftBGImage.frame.size.width, height: leftBGImage.frame.size.height)
leftBGImage.layer.mask = mask
leftBGImage.layer.masksToBounds = true

回答by Nick Weaver

The tutorial uses this method with two parameters: imageand maskImage, these you have to set when you call the method. An example call could look like this, assuming the method is in the same class and the pictures are in your bundle:

本教程使用带有两个参数的此方法:imagemaskImage,您必须在调用该方法时设置这些参数。示例调用可能如下所示,假设该方法在同一个类中并且图片在您的包中:

Note - amazingly the images do not even have to be the same size.

注意 - 令人惊讶的是,图像甚至不必是相同的大小。

...
UIImage *image = [UIImage imageNamed:@"dogs.png"];
UIImage *mask = [UIImage imageNamed:@"mask.png"];

// result of the masking method
UIImage *maskedImage = [self maskImage:image withMask:mask];

...

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef maskedImageRef = CGImageCreateWithMask([image CGImage], mask);
    UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];

    CGImageRelease(mask);
    CGImageRelease(maskedImageRef);

    // returns new image with mask applied
    return maskedImage;
}

After you provided your code I have added some numbers as comments to it for reference. You still have two options. This whole thing is a method, which you are calling somewhere. You don't need to create the images inside it: this reduces the reusability of the method to zero.

在您提供代码后,我添加了一些数字作为注释以供参考。你还有两个选择。这整个事情是一个方法,你在某处调用它。您不需要在其中创建图像:这会将方法的可重用性降低到零。

To get your code working. Change the methods head (1.) to

让你的代码工作。将方法头 ( 1.)更改为

- (UIImage *)maskImageMyImages {

Then change the name of the variable in 2.to

然后将2.中的变量名称更改为

UIImage *maskImage = [UIImage imageNamed:@"mask.png"];

The method will return your masked images so you'll have to call this method in some place. Can you show us the code where you are calling your method?

该方法将返回您的蒙版图像,因此您必须在某个地方调用此方法。你能告诉我们你调用方法的代码吗?

回答by Mark Moeykens

Swift 3 - Simplest Solution I Found

Swift 3 - 我找到的最简单的解决方案

I created an @IBDesignablefor this so you could see the effect right away on your storyboard.

@IBDesignable为此创建了一个,以便您可以立即在故事板上看到效果。

import UIKit

@IBDesignable
class UIImageViewWithMask: UIImageView {
    var maskImageView = UIImageView()

    @IBInspectable
    var maskImage: UIImage? {
        didSet {
            maskImageView.image = maskImage
            updateView()
        }
    }

    // This updates mask size when changing device orientation (portrait/landscape)
    override func layoutSubviews() {
        super.layoutSubviews()
        updateView()
    }

    func updateView() {
        if maskImageView.image != nil {
            maskImageView.frame = bounds
            mask = maskImageView
        }
    }
} 

How to use

如何使用

  1. Create a new file and paste in that code above.
  2. Add UIImageView to your storyboard (assign an image if you want).
  3. On Identity Inspector: Change the custom class to "UIImageViewWithMask" (custom class name above).
  4. On Attributes Inspector: Select mask image you want to use.
  1. 创建一个新文件并粘贴上面的代码。
  2. 将 UIImageView 添加到您的故事板(如果需要,可以分配图像)。
  3. 在 Identity Inspector 上:将自定义类更改为“UIImageViewWithMask”(上面的自定义类名)。
  4. 在属性检查器上:选择要使用的蒙版图像。

Example

例子

Masking on Storyboard

故事板上的遮罩

Notes

笔记

  • Your mask image should have a transparent background (PNG) for the non-black part.
  • 您的蒙版图像的非黑色部分应具有透明背景 (PNG)。

回答by Ninji

I tried both code using either CALayer or CGImageCreateWithMask but none of them didn't work for me

我使用 CALayer 或 CGImageCreateWithMask 尝试了这两个代码,但没有一个对我不起作用

But i found out that the problem is with png file format, NOT the code!!
so just to share my finding!

但我发现问题在于 png 文件格式,而不是代码!!
所以只是分享我的发现!

If you want to use

如果你想使用

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage

you must use 24bitpng withoutalpha channel

你必须使用没有alpha 通道的24 位png

If you want to use CALayer mask, you must use (24bit or 8bit) png withalpha channel where transparent part of your png will mask the image (for smooth gradient alpha mask.. use 24bit png with alpha channel)

如果要使用 CALayer 蒙版,则必须使用(24 位或 8 位)pngalpha 通道,其中 png 的透明部分将掩盖图像(对于平滑渐变 alpha 蒙版..使用 24 位 png 和 alpha 通道)

回答by ZYiOS

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGImageRef maskImageRef = [maskImage CGImage];

        // create a bitmap graphics context the size of the image
        CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(colorSpace);

        if (mainViewContentContext==NULL)
            return NULL;

        CGFloat ratio = 0;

        ratio = maskImage.size.width/ image.size.width;

        if(ratio * image.size.height < maskImage.size.height) {
            ratio = maskImage.size.height/ image.size.height;
        }

        CGRect rect1  = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
        CGRect rect2  = {{-((image.size.width*ratio)-maskImage.size.width)/2 , -((image.size.height*ratio)-maskImage.size.height)/2}, {image.size.width*ratio, image.size.height*ratio}};


        CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
        CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);


        // Create CGImageRef of the main view bitmap content, and then
        // release that bitmap context
        CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
        CGContextRelease(mainViewContentContext);

        UIImage *theImage = [UIImage imageWithCGImage:newImage];

        CGImageRelease(newImage);

        // return the image
        return theImage;
}

This works for me.

这对我有用。

回答by Ahmed Safadi

SWIFT 3 XCODE 8.1

SWIFT 3 XCODE 8.1

func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {

    let maskRef = maskImage.cgImage

    let mask = CGImage(
        maskWidth: maskRef!.width,
        height: maskRef!.height,
        bitsPerComponent: maskRef!.bitsPerComponent,
        bitsPerPixel: maskRef!.bitsPerPixel,
        bytesPerRow: maskRef!.bytesPerRow,
        provider: maskRef!.dataProvider!,
        decode: nil,
        shouldInterpolate: false)

    let masked = image.cgImage!.masking(mask!)
    let maskedImage = UIImage(cgImage: masked!)

    // No need to release. Core Foundation objects are automatically memory managed.

    return maskedImage

}

// for use

// 用来

testImage.image = maskImage(image: UIImage(named: "OriginalImage")!, withMask: UIImage(named: "maskImage")!)

回答by Juan Valera

Swift version of the accepted solution:

已接受解决方案的 Swift 版本:

func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {

    let maskRef = maskImage.CGImage

    let mask = CGImageMaskCreate(
        CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef),
        nil,
        false)

    let masked = CGImageCreateWithMask(image.CGImage, mask)
    let maskedImage = UIImage(CGImage: masked)!

    // No need to release. Core Foundation objects are automatically memory managed.

    return maskedImage

}

Just in case someone need it.

以防万一有人需要它。

It`s working for me flawlessly.

它完美地为我工作。

回答by werbary

we found, that correct answer is not working now and implemented little drop-in class, which helps to mask any image in UIImageView.

我们发现,正确的答案现在不起作用,并实现了小的插入类,这有助于屏蔽 UIImageView 中的任何图像。

It's available here: https://github.com/Werbary/WBMaskedImageView

它可以在这里找到:https: //github.com/Werbary/WBMaskedImageView

Example:

例子:

WBMaskedImageView *imgView = [[WBMaskedImageView alloc] initWithFrame:frame];
imgView.originalImage = [UIImage imageNamed:@"original_image.png"];
imgView.maskImage = [UIImage imageNamed:@"mask_image.png"];