Làm cách nào để đặt độ mờ / alpha của UIImage?


81

Tôi biết bạn có thể làm điều này với UIImageView, nhưng liệu nó có thể thực hiện được với UIImage không? Tôi muốn có thuộc tính mảng hình ảnh động của UIImageView là một mảng của cùng một hình ảnh nhưng có độ mờ khác nhau. Suy nghĩ?

Câu trả lời:


122

Tôi chỉ cần làm điều này, nhưng nghĩ rằng giải pháp của Steven sẽ chậm. Điều này hy vọng sẽ sử dụng HW đồ họa. Tạo một danh mục trên 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
thậm chí không thể nhớ tại sao tôi cần :) này
Marty

Giải pháp tuyệt vời! Xin cảm ơn Nick!
Christopher

1
Chỉ cần đảm bảo rằng bạn đang gọi UIGraphicsBeginImageContextWithOptions trên luồng chính vì kết xuất nền sẽ không thể đoán trước được.
Steven Veltema

1
Theo Apple, bạn có thể gọi UIGraphicsBeginImageContextWithOptions trên bất kỳ luồng nào kể từ iOS 4 trở lên.
Ants

6
Hoạt động tốt, cảm ơn rất nhiều. Đối với những người mới tham gia hậu cần xung quanh việc phát triển iOS, đây là các bước để tạo một danh mục cho UIImage. 1. Nhấp chuột phải vào giám đốc dự án của bạn và chọn Tệp Mới. 2. Trong màn hình xuất hiện, chọn loại tệp danh mục Objective-C. 3. Thêm mã của câu trả lời vào tệp .m và khai báo cho phương thức trong tệp .h. 4. Trong tệp sử dụng hình ảnh để trong suốt, hãy # nhập tệp. 5. Sử dụng phương thức imageByApplyingAlpha trên một phiên bản của UIImage.
Danny

79

Đặt độ mờ của chế độ xem mà nó được hiển thị.

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

Sử dụng điều này trong một hình ảnh động. Bạn có thể thay đổi alpha trong hoạt ảnh trong một khoảng thời gian.

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

vâng tôi đã nghĩ rằng tôi có thể phải làm như vậy với bộ đếm thời gian để thay đổi độ mờ liên tục, chỉ nghĩ rằng sẽ dễ dàng hơn nhiều nếu có một mảng cho thuộc tính mảng hình ảnh động để nó tự hoạt động.
Marty

Bạn có thể tạo hoạt ảnh 'vào' và 'ra' giống như một nhịp tim với đại biểu hoạt ảnh. Không sử dụng bộ đếm thời gian, hoạt ảnh sẽ thay đổi alpha mượt mà. Chúc may mắn.
Mats Stijlaart

3
Điều này chỉ hoạt động nếu nhà phát triển đang sử dụng UIImageView. Câu hỏi rõ ràng nói rằng không phải như vậy.
Raul Huerta

1
Điều này hoạt động với UIImage được trình bày trong CALayer, chỉ bạn đặt layer.opacity mà không cần phải sửa đổi hình ảnh nào cả. Cảm ơn Mats!
Chris

Tuyệt quá! Hoạt động trên UIButton, chính xác những gì tôi cần.
NecipAllef

52

Dựa trên câu trả lời của Alexey Ishkov, nhưng bằng Swift

Tôi đã sử dụng phần mở rộng của lớp UIImage.

Swift 2:

Tiện ích mở rộng hình ảnh:

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

Để sử dụng:

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

Nhanh 3/4/5:

Lưu ý rằng triển khai này trả về một UIImage tùy chọn. Điều này là do trong Swift 3 UIGraphicsGetImageFromCurrentImageContextbây giờ trả về một tùy chọn. Giá trị này có thể là nil nếu ngữ cảnh là nil hoặc những gì không được tạo bằng UIGraphicsBeginImageContext.

Tiện ích mở rộng hình ảnh:

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

Để sử dụng:

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

Tôi thích Swift 3phiên bản này hơn.
AechoLiu

Cảm ơn. Nó hoạt động tương tự trong Swift 4, tôi đã cập nhật câu trả lời để phản ánh điều này.
zeeshan

Bravo sir, bravo
Ryan Brodie

17

có nhiều giải pháp dễ dàng hơn:

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

1
Có lẽ nên là câu trả lời được chấp nhận. Nhanh nhất / nhất cách hiệu quả để có được kết quả
Will Von Ullrich

4

Tôi nhận ra điều này là khá muộn, nhưng tôi cần một cái gì đó như thế này vì vậy tôi đã đưa ra một phương pháp nhanh chóng và bẩn thỉu để thực hiện việc này.

+ (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
Tên tốt hơn sẽ làsetImage:withAlpha:
Alexander

8
set thường tham chiếu đến các thuộc tính, theo một cách nào đó thay đổi trạng thái của máy thu. sẽ tốt hơn nếu đặt tên cho nó image:withAlpha:?
Jonathan.

2
Vâng. Việc gọi set cũng áp dụng cài đặt cùng một đối tượng được chuyển vào, thay vì trả về một hình ảnh mới.
hệ thống

4

Này này, cảm ơn từ người dùng Xamarin! :) Ở đây nó được dịch sang 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;
        }

}

Ví dụ sử dụng:

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

1

kết quả giống như những người khác, phong cách khác nhau:

extension UIImage {

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

}

1

Swift 5:

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

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

0

Nếu bạn đang thử nghiệm với kết xuất Metal và bạn đang trích xuất CGImage được tạo bởi imageByApplyingAlpha trong câu trả lời đầu tiên, bạn có thể kết thúc với một bản dựng Metal lớn hơn bạn mong đợi. Trong khi thử nghiệm với Metal, bạn có thể muốn thay đổi một dòng mã trong imageByApplyingAlpha:

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

Nếu bạn đang sử dụng thiết bị có hệ số tỷ lệ 3.0, như iPhone 11 Pro Max, hệ số tỷ lệ 0.0 được hiển thị ở trên sẽ cung cấp cho bạn hình ảnh CGI lớn hơn gấp ba lần so với mức bạn mong đợi. Thay đổi hệ số tỷ lệ thành 1,0 sẽ tránh bất kỳ tỷ lệ nào.

Hy vọng rằng, trả lời này sẽ cứu những người mới bắt đầu rất nhiều trầm trọng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.