UIImage의 불투명도 / 알파를 설정하는 방법은 무엇입니까?


81

UIImageView로 이것을 할 수 있다는 것을 알고 있지만 UIImage로 할 수 있습니까? UIImageView의 애니메이션 이미지 배열 속성을 동일한 이미지의 배열이지만 다른 불투명도를 갖기를 원합니다. 생각?

답변:


122

이 작업을 수행해야했지만 Steven의 솔루션이 느릴 것이라고 생각했습니다. 이것은 그래픽 HW를 사용하기를 바랍니다. UIImage에 카테고리를 만듭니다.

- (UIImage *)imageByApplyingAlpha:(CGFloat) alpha {
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGRect area = CGRectMake(0, 0, self.size.width, self.size.height);

    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -area.size.height);

    CGContextSetBlendMode(ctx, kCGBlendModeMultiply);

    CGContextSetAlpha(ctx, alpha);

    CGContextDrawImage(ctx, area, self.CGImage);

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

3
왜 내가 이것을 필요로했는지 기억할 수 없습니다 :)
Marty

훌륭한 솔루션! 닉 감사합니다!
Christopher

1
백그라운드 렌더링을 예측할 수 없기 때문에 메인 스레드에서 UIGraphicsBeginImageContextWithOptions를 호출하고 있는지 확인하십시오.
Steven Veltema

1
Apple에 따르면 iOS 4 이상 이후 모든 스레드에서 UIGraphicsBeginImageContextWithOptions를 호출 할 수 있습니다.
Ants

6
대단히 감사합니다. iOS 개발 관련 물류에 대한 다른 초보자를 위해 다음은 UIImage에 대한 카테고리를 만드는 단계입니다. 1. 프로젝트 디렉터를 마우스 오른쪽 버튼으로 클릭하고 새 파일을 선택합니다. 2. 나타나는 화면에서 Objective-C 범주 파일 유형을 선택합니다. 3. .m 파일에 응답 코드를 추가하고 .h 파일에 메서드 선언을 추가합니다. 4. 이미지를 투명하게 사용하는 파일에서 파일을 #import합니다. 5. UIImage의 인스턴스에서 imageByApplyingAlpha 메서드를 사용합니다.
Danny

79

표시되는 뷰의 불투명도를 설정합니다.

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithName:@"SomeName.png"]];
imageView.alpha = 0.5; //Alpha runs from 0.0 to 1.0

애니메이션에서 이것을 사용하십시오. 일정 기간 동안 애니메이션에서 알파를 변경할 수 있습니다.

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
//Set alpha
[UIView commitAnimations];

그래 나는 불투명도를 지속적으로 변경하기 위해 타이머를 사용하여 이와 같이해야 할 수도 있다고 생각하고 있었지만 애니메이션 이미지 배열 속성에 대한 배열을 갖는 것이 훨씬 더 쉬울 것이라고 생각하여 자체적으로 애니메이션을 적용했습니다.
Marty

애니메이션 델리게이트를 사용하여 하트 비트처럼 'in'및 'out'애니메이션을 적용 할 수 있습니다. 타이머를 사용하지 마십시오. 애니메이션이 알파를 부드럽게 변경합니다. 행운을 빕니다.
Mats Stijlaart

3
이것은 개발자가 UIImageView를 사용하는 경우에만 작동합니다. 질문은 그것이 사실이 아니라고 분명히 말합니다.
Raul Huerta

1
이것은 CALayer에 표시된 UIImage와 함께 작동하며 이미지를 전혀 수정하지 않고 layer.opacity를 설정하기 만하면됩니다. 감사합니다 Mats!
Chris

큰! 에서 작동합니다 UIButton. 정확히 필요한 것입니다.
NecipAllef

52

Alexey Ishkov의 답변을 기반으로하지만 Swift

UIImage 클래스의 확장을 사용했습니다.

스위프트 2 :

UIImage 확장 :

extension UIImage {
    func imageWithAlpha(alpha: CGFloat) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        drawAtPoint(CGPointZero, blendMode: .Normal, alpha: alpha)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}

쓰다:

let image = UIImage(named: "my_image")
let transparentImage = image.imageWithAlpha(0.5)

스위프트 3/4/5 :

이 구현은 선택적 UIImage를 반환합니다. 이는 Swift 3에서 UIGraphicsGetImageFromCurrentImageContext이제 선택 사항을 반환 하기 때문입니다 . 컨텍스트가 nil이거나로 생성되지 않은 경우이 값은 nil 일 수 있습니다 UIGraphicsBeginImageContext.

UIImage 확장 :

extension UIImage {
    func image(alpha: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        draw(at: .zero, blendMode: .normal, alpha: alpha)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}

쓰다:

let image = UIImage(named: "my_image")
let transparentImage = image?.image(alpha: 0.5)

Swift 3버전을 선호합니다 .
AechoLiu 2011

감사. Swift 4에서도 동일하게 작동하며이를 반영하기 위해 답변을 업데이트했습니다.
zeeshan

브라보 선생님, 브라보
Ryan Brodie

17

훨씬 더 쉬운 해결책이 있습니다.

- (UIImage *)tranlucentWithAlpha:(CGFloat)alpha
{
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [self drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:alpha];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

1
아마도 받아 들여진 대답 이었어 야했다. 결과를 얻을 수있는 가장 빠른 / 가장 효율적인 방법
윌 폰 울리히

4

나는 이것이 꽤 늦다는 것을 알고 있지만 이와 같은 것이 필요했기 때문에 이것을 수행하기 위해 빠르고 더러운 방법을 채찍질했습니다.

+ (UIImage *) image:(UIImage *)image withAlpha:(CGFloat)alpha{

    // Create a pixel buffer in an easy to use format
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    UInt8 * m_PixelBuf = malloc(sizeof(UInt8) * height * width * 4);

    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(m_PixelBuf, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    //alter the alpha
    int length = height * width * 4;
    for (int i=0; i<length; i+=4)
    {
        m_PixelBuf[i+3] =  255*alpha;
    }


    //create a new image
    CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGImageRef newImgRef = CGBitmapContextCreateImage(ctx);  
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(ctx);  
    free(m_PixelBuf);

    UIImage *finalImage = [UIImage imageWithCGImage:newImgRef];
    CGImageRelease(newImgRef);  

    return finalImage;
}

2
더 좋은 이름이 될 것이다setImage:withAlpha:
알렉산더

8
set는 일반적으로 속성을 참조하며 어떤 방식 으로든 수신자의 상태를 변경합니다. 이름을 지정하는 것이 더 image:withAlpha:좋을까요?
조나단.

2
네. 또한 set를 호출하면 새 이미지를 반환하는 대신 전달 된 동일한 객체 설정이 적용됩니다.
시스템

4

Xamarin 사용자로부터 감사합니다! :) 여기에 C #으로 번역됩니다.

//***************************************************************************
public static class ImageExtensions
//***************************************************************************
{
    //-------------------------------------------------------------
    public static UIImage WithAlpha(this UIImage image, float alpha)  
    //-------------------------------------------------------------
        {
        UIGraphics.BeginImageContextWithOptions(image.Size,false,image.CurrentScale);
        image.Draw(CGPoint.Empty, CGBlendMode.Normal, alpha);
        var newImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();
        return newImage;
        }

}

사용 예 :

var MySupaImage = UIImage.FromBundle("opaquestuff.png").WithAlpha(0.15f);

1

다른 스타일과 동일한 결과 :

extension UIImage {

    func withAlpha(_ alpha: CGFloat) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(at: .zero, blendMode: .normal, alpha: alpha)
        }
    }

}

1

스위프트 5 :

extension UIImage {
  func withAlphaComponent(_ alpha: CGFloat) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(size, false, scale)
    defer { UIGraphicsEndImageContext() }

    draw(at: .zero, blendMode: .normal, alpha: alpha)
    return UIGraphicsGetImageFromCurrentImageContext()
  }
}

0

Metal 렌더링을 실험하고 있고 첫 번째 응답에서 imageByApplyingAlpha에 의해 생성 된 CGImage를 추출하는 경우 예상보다 큰 Metal 렌더링으로 끝날 수 있습니다. Metal로 실험하는 동안 imageByApplyingAlpha에서 코드 한 줄을 변경할 수 있습니다.

    UIGraphicsBeginImageContextWithOptions (self.size, NO, 1.0f);
//  UIGraphicsBeginImageContextWithOptions (self.size, NO, 0.0f);

iPhone 11 Pro Max와 같이 배율이 3.0 인 기기를 사용하는 경우 위에 표시된 0.0 배율은 예상보다 3 배 더 큰 CGImage를 제공합니다. 배율을 1.0으로 변경하면 배율이 조정되지 않습니다.

바라건대,이 답변이 초보자들에게 많은 고통을 덜어 주길 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.