Programing

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

lottogame 2020. 8. 24. 20:49
반응형

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


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

마스킹 할 이미지

제발 도와 주 시겠어요?

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

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

더 쉬운 방법이 있습니다.

#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

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

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


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)이 있어야합니다.

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

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

If you want to use

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

you must use 24bit png without alpha channel

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


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


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

Swift version of the accepted solution:

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.


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

참고 URL : https://stackoverflow.com/questions/5757386/how-can-i-mask-a-uiimageview

반응형