UIImageView를 마스크하려면 어떻게해야합니까?


100

다음과 같이 이미지를 가려 보려고합니다.

마스킹 할 이미지

제발 도와 주 시겠어요?

이 코드를 사용하고 있습니다.

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

27
나는 원래 튜토리얼을 작성한 사람입니다. 마스크 이미지는 포토샵에서 만든 단순한 그레이 스케일 이미지입니다. 그것에 대해 특별한 것은 없습니다. 검은 색 영역은 마스크의 "투명한"부분이됩니다. 회색 음영은 불투명도의 정도로 해석됩니다. 이러한 방식으로 마스크 주변에 더 부드러운 테두리를 만드는 데 유용한 그라디언트가 될 수도 있습니다.
ra9r

크기가 같아야 하죠?
KarenAnne 2013

매우 우아한 코드, 감사합니다. 누군가가 마스킹하기 전에 이미지를
잘라야


1
선택한 답변을 거의 3 배의 찬성 투표로 변경해 주시기 바랍니다. 제 생각에는 거의 모든면에서 더 좋습니다.
Albert Renshaw

답변:


163

더 쉬운 방법이 있습니다.

#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

1
고맙지 만이 코드를 입력 viewDidLoad했지만 아무 일도 일어나지 않았습니다!
Mc.Lover 2011-04-23

6
마스크를 사용하려면 레이어 속성을 설정해야합니다. 즉 [yourImageView.layer setMasksToBounds : YES];
Wolfgang Schreurs 2011

3
이 솔루션의 UIImageView 여야합니다. 다른 솔루션은 UIImage에서만 작동합니다.
adriendenat

1
이 방법을 시도했지만 iOS 8에서 작동하지 않는 것 같습니다
bdv

2
Swift 코드의 경우 mask.contents에 넣으면 CGImage가 있어야합니다. [CGImage]가 아닙니다. 대괄호 []를 사용하면 배열을 의미합니다.
strawnut

59

자습서에서는이 메서드를 두 개의 매개 변수와 함께 사용합니다. 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;
}

코드를 제공 한 후 참조를 위해 주석으로 몇 가지 번호를 추가했습니다. 여전히 두 가지 옵션이 있습니다. 이 모든 것은 당신이 어딘가에서 호출하고있는 메서드입니다. 내부에 이미지를 만들 필요가 없습니다. 이렇게하면 메서드의 재사용 가능성이 0으로 줄어 듭니다.

코드를 작동 시키려면. 메소드 헤드 ( 1. )를

- (UIImage *)maskImageMyImages {

그런 다음 2 의 변수 이름 을

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

이 메서드는 마스크 된 이미지를 반환하므로 어떤 위치에서이 메서드를 호출해야합니다. 메서드를 호출하는 코드를 보여줄 수 있습니까?


죄송합니다 ! UIImage *image코드 는 어디에 작성해야 합니까? !!! -(UIimage *) maskeImage컴파일러에서 재정의 오류가 발생 하기 때문입니다 !
Mc.Lover 2011-04-22

죄송합니다. 샘플 코드를 업로드 해 주시겠습니까? Iam 혼란 스러워요 : -s
Mc.Lover 2011

1
불가능합니다. 모든 것이 있습니다. 이 메서드를 어떻게 호출하는지 또는 적어도 이미지를 마스킹하고 결과를 표시 할 부분을 보여 주어야합니다.
Nick Weaver

내 문제는 그것을 호출하는 것입니다. (있는 viewDidLoad가) : 내 편집 코드 참조
Mc.Lover

리버스 마스킹에 대한 아이디어 (위 과정의 반대) 채우기 영역 (투명하게)과 채우기가있는 투명 영역을 제거하고 싶습니다.
Milan patel 15.01.23

16

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. 속성 검사기에서 : 사용할 마스크 이미지를 선택합니다.

스토리 보드에서 마스킹

노트

  • 마스크 이미지에는 검정색이 아닌 부분에 대해 투명한 배경 (PNG)이 있어야합니다.

12

CALayer 또는 CGImageCreateWithMask를 사용하여 두 코드를 모두 시도했지만 어느 것도 나를 위해 작동하지 않았습니다.

하지만 문제가 코드가 아닌 png 파일 형식이라는 것을 알았습니다!
내 발견을 공유하기 위해!

사용하려는 경우

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

알파 채널 없이 24 비트 png 를 사용해야합니다.

CALayer 마스크를 사용하려면 png의 투명한 부분이 이미지를 마스킹하는 알파 채널 과 함께 (24 비트 또는 8 비트) png를 사용해야합니다 ( 부드러운 그래디언트 알파 마스크의 경우 알파 채널이있는 24 비트 png 사용).


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

이것은 나를 위해 작동합니다.


감사합니다.이 대답은 다른 사람이 점점 더 큰 이미지로 성능에 대해 말하는 것보다 낫습니다.
Radu Ursache 2014

1
리버스 마스킹에 대한 아이디어 (위 과정의 반대) 채우기 영역 (투명하게)과 채우기가있는 투명 영역을 제거하고 싶습니다.
Milan patel 2015 년

감사합니다.이 코드는 처음보다 잘 작동합니다 !! 하지만 두 가지 문제가 있습니다. "kCGImageAlphaPremultipliedLast"에 대한 경고 (수정을 위해 "CGBitmapInfo"로 캐스트) 및 망막 이미지에서 작동하지 않습니다! 당신이 나를 도울 수 ?? ...
fingerup

@Milanpatel 쉬운 해결책은 마스크 이미지에서 색상을 반전시키는 것입니다. :)
Dids

@ZyiOS 마스킹 된 이미지의 프레임을 어떻게 사용자 정의 할 수 있습니까? 즉, 사용자는 마스킹 된 이미지의 크기를 늘리거나 줄일 수 있습니다.
Dalvik

8

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")!)

당신은 나에게 사진을 제공 할 수 있습니다
아메드 Safadi에게

3

허용되는 솔루션의 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 버전이 있습니까?
Van Du Tran 2016

2

우리는 정답이 현재 작동하지 않고 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"];

1
잘 했어! 정말 도움이되었습니다.
abhimuralidharan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.