Як встановити непрозорість / альфа-зображення UIImage?


83

Я знаю, що ви можете зробити це за допомогою UIImageView, але чи можна це зробити для UIImage? Я хочу, щоб властивість масиву анімаційних зображень UIImageView була масивом того самого зображення, але з різною непрозорістю. Думки?

Відповіді:


122

Мені просто потрібно було це зробити, але думав, що рішення Стівена буде повільним. Сподіваємось, тут слід використовувати графіку 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
навіть не можу згадати, навіщо мені це було потрібно :)
— Марті

Чудове рішення! Дякую Ніку!
— Крістофер,

1
Тільки переконайтеся, що ви викликаєте UIGraphicsBeginImageContextWithOptions в основному потоці, оскільки фонове відтворення буде непередбачуваним.
— Steven Veltema

1
За словами Apple, ви можете викликати UIGraphicsBeginImageContextWithOptions у будь-якому потоці, починаючи з iOS 4 і пізніших версій.
— Мурахи

6
Чудово працює, спасибі тонна. Для інших новачків у логістиці навколо розробки iOS, ось кроки для створення категорії для UIImage. 1. Клацніть правою кнопкою миші в режисері проекту та виберіть Новий файл. 2. На екрані, що з’явиться, виберіть тип файлу категорії Objective-C. 3. Додайте код відповіді у файл .m та декларацію методу у файл .h. 4. У файлі, в якому зображення використовується прозорим, # імпортуйте файл. 5. Використовуйте метод imageByApplyingAlpha на екземплярі UIImage.
— Денні

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

так, я думав, що мені, можливо, доведеться робити це так за допомогою таймера, щоб постійно змінювати непрозорість, просто думав, що буде набагато простіше мати масив для властивості масиву анімаційних зображень, щоб він анімував сам по собі.
— Марті

Ви можете анімувати це "в" і "назовні", як серцебиття за допомогою делегата анімації. Не використовуйте таймер, анімація плавно змінить альфу. Удачі.
— Mats Stijlaart

3
Це працює, лише якщо розробник використовує UIImageView. Питання чітко говорить, що це не так.
— Raul Huerta

1
Це працює з UIImage, представленим у CALayer, лише ви встановлюєте layer.opacity, не змінюючи зображення взагалі. Дякую Матс!
— Кріс

Чудово! Працює над тим UIButton, що саме мені було потрібно.
— NecipAllef

53

Засноване на відповіді Олексія Ішкова, але на швидкому

Я використовував розширення класу 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тепер повертається необов’язковий. Це значення може бути нульовим, якщо контекст нульовий або те, що не створено за допомогою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

Дякую. Це працює так само в Swift 4, я оновив відповідь, щоб це відобразити.
— zeeshan

Браво, сер, браво
— Райан Броді

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
набір зазвичай відноситься до властивостей, певним чином змінюючи стан приймача. краще б його назвати image:withAlpha:?
— Джонатан.

2
Ага. Також для виклику набору застосовується встановлення того самого об'єкта, який передано, а не повернення нового зображення.
— системний

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

Якщо ви експериментуєте з візуалізацією металу і ви витягуєте CGImage, сформований imageByApplyingAlpha у першій відповіді, у вас може вийти візуалізація металу, яка більша, ніж ви очікуєте. Під час експериментів з Metal ви можете змінити один рядок коду в imageByApplyingAlpha:

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

Якщо ви використовуєте пристрій із коефіцієнтом масштабу 3,0, наприклад iPhone 11 Pro Max, показаний вище коефіцієнт 0,0 дасть вам CGImage, який у три рази перевищує очікуваний. Змінюючи коефіцієнт масштабу до 1,0, слід уникати масштабування.

Сподіваємось, ця відповідь позбавить початківців значного загострення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.