【问题标题】:How can I mask a UIImageView?如何屏蔽 UIImageView?
【发布时间】:2011-08-11 01:44:36
【问题描述】:

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

你能帮帮我吗?

我正在使用此代码:

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

【问题讨论】:

  • 我是编写原始教程的人。蒙版图像只是我在 Photoshop 中创建的简单灰度图像。没什么特别的。黑色区域成为蒙版的“透明”部分。请记住,任何灰色阴影都被解释为一定程度的不透明度。通过这种方式,蒙版也可以是渐变色,这对于在蒙版周围创建更柔和的边框很有用。
  • 这个大小应该一样吧?
  • 超优雅的代码,谢谢。如果有人需要在屏蔽之前裁剪图像,这只是一个有用的链接...stackoverflow.com/questions/17712797/…
  • 关于这个的任何想法..stackoverflow.com/questions/28122370/…
  • 我敦促您将所选答案更改为投票数几乎是 3 倍的答案。在我看来,几乎所有方面都更好。

标签: ios objective-c uiimage mask


【解决方案1】:

有一个更简单的方法。

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

对于 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

【讨论】:

  • 谢谢,但我把这段代码放在viewDidLoad 上,但什么也没发生!
  • 你应该设置图层属性来使用遮罩,即[yourImageView.layer setMasksToBounds:YES];
  • 请注意,对于此解决方案,这是一个 UIImageView 所必需的。另一种解决方案仅适用于 UIImage。
  • 我尝试了这种方法,但这似乎不适用于 iOS 8
  • 对于 Swift 代码,当放入 mask.contents 时,应该是 CGImage。不是[CGImage]。如果使用括号[],则表示数组。
【解决方案2】:

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

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

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

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

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

- (UIImage *)maskImageMyImages {

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

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

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

【讨论】:

  • 对不起!应该在哪里写UIImage *image 代码? !!!因为在-(UIimage *) maskeImage 编译器给出了重新定义错误!
  • 抱歉,您能帮我上传一个示例代码吗?我很困惑:-s
  • 不可能,一切都在那里。您必须向我们展示您是如何调用此方法的,或者至少向我们展示您想要遮盖图像并显示结果的部分。
  • 我的问题是调用它,它应该是这样的吗?? (viewDidLoad): 查看我编辑的代码
  • 关于反向遮罩的任何想法。(上述过程的反向)。意味着我想删除填充区域(使其透明)和透明区域填充。
【解决方案3】:

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

我为此创建了一个@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
        }
    }
} 

如何使用

  1. 创建一个新文件并粘贴上面的代码。
  2. 将 UIImageView 添加到您的故事板(如果需要,分配图像)。
  3. 在 Identity Inspector 上:将自定义类更改为“UIImageViewWithMask”(上面的自定义类名称)。
  4. On Attributes Inspector:选择蒙版图像 想用。

示例

注意事项

  • 您的蒙版图片的非黑色部分应具有透明背景 (PNG)。

【讨论】:

    【解决方案4】:

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

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

    如果你想使用

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

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

    如果你想使用 CALayer 蒙版,你必须使用(24bit 或 8bit)png with alpha 通道,你的 png 的透明部分会屏蔽图像(对于平滑渐变 alpha 蒙版.. 使用 24bit png 带 alpha 通道)

    【讨论】:

      【解决方案5】:
      - (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;
      }
      

      这对我有用。

      【讨论】:

      • 谢谢,这个答案比其他人谈论更多更大图像的性能要好。
      • 关于反向遮罩的任何想法。(与上述过程相反)。意味着我想删除填充区域(使其透明)和填充透明区域。
      • 谢谢,这个代码比第一个更好!但我有两个麻烦:警告“kCGImageAlphaPremultipliedLast”(我投到“CGBitmapInfo”来修复它)并且不适用于视网膜图像!你能帮我吗??...
      • @Milanpatel 简单的解决方案是简单地反转蒙版图像中的颜色。 :)
      • @ZyiOS 如何自定义蒙版图像的框架。即用户可以增加或减少蒙版图像的大小。
      【解决方案6】:

      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
      
      }
      

      //供使用

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

      【讨论】:

      • 你能给我图片吗
      【解决方案7】:

      已接受解决方案的 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
      
      }
      

      以防万一有人需要。

      它完美地为我工作。

      【讨论】:

      • 你有这个的 Swift 3.0 版本吗?
      【解决方案8】:

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

      可在此处获取:https://github.com/Werbary/WBMaskedImageView

      例子:

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

      【讨论】:

      • 好一个!真的很有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-06
      • 2015-01-08
      • 2013-06-09
      • 1970-01-01
      • 1970-01-01
      • 2017-01-01
      相关资源
      最近更新 更多