Как установить непрозрачность / альфа UIImage?

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


person Marty    schedule 22.02.2011    source источник


Ответы (9)


Мне просто нужно было это сделать, но я думал, что решение Стивена будет медленным. Надеюсь, это должно использовать графическое 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;
}
person Nick H247    schedule 30.05.2012
comment
даже не могу вспомнить, зачем мне это было нужно :) - person Marty; 31.05.2012
comment
Отличное решение! Спасибо, Ник! - person Christopher; 19.06.2012
comment
Просто убедитесь, что вы вызываете UIGraphicsBeginImageContextWithOptions в основном потоке, потому что отрисовка фона будет непредсказуемой. - person Steven Veltema; 15.11.2012
comment
Согласно Apple, вы можете вызвать UIGraphicsBeginImageContextWithOptions в любом потоке, начиная с iOS 4 и более поздних версий. - person Ants; 08.01.2013
comment
Отлично работает, большое спасибо. Для других новичков в логистике, связанной с разработкой iOS, вот шаги по созданию категории для UIImage. 1. Щелкните правой кнопкой мыши в директории вашего проекта и выберите «Новый файл». 2. На появившемся экране выберите тип файла категории Objective-C. 3. Добавьте код ответа в файл .m и объявление метода в файл .h. 4. В файле, который использует изображение, чтобы быть прозрачным, # импортируйте файл. 5. Используйте метод imageByApplyingAlpha для экземпляра UIImage. - person Danny; 22.02.2013
comment
Если вы ищете решение для применения непрозрачности к UIImage, которое вы хотите использовать в качестве кнопки на панели навигации (возможно, для выделенного состояния), используйте это решение. Идеально работал у меня в iOS 7.1. - person Alex; 26.05.2014

Установите непрозрачность вида, в котором он отображается.

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];
person Mats Stijlaart    schedule 22.02.2011
comment
да, я думал, что мне, возможно, придется сделать это с таймером, чтобы постоянно изменять непрозрачность, просто подумал, что было бы намного проще иметь массив для свойства массива изображений анимации, чтобы он анимировал сам по себе. - person Marty; 23.02.2011
comment
Вы можете анимировать его «вход» и «выход», как сердцебиение, с помощью делегата анимации. Не используйте таймер, анимация плавно изменит альфа-канал. Удачи. - person Mats Stijlaart; 23.02.2011
comment
Это работает, только если разработчик использует UIImageView. Вопрос ясно говорит, что это не так. - person Raul Huerta; 27.08.2014
comment
Это работает с UIImage, представленным в CALayer, только вы устанавливаете layer.opacity без необходимости вообще изменять изображение. Спасибо, Матс! - person Chris; 21.07.2015
comment
Большой! Работает на UIButton, именно то, что мне нужно. - person NecipAllef; 27.04.2016

На основе ответа Алексея Ишкова, но на Swift

Я использовал расширение класса UIImage.

Swift 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)

Swift 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)
person Devin Brown    schedule 21.06.2016
comment
Я предпочитаю эту Swift 3 версию. - person AechoLiu; 03.11.2017
comment
Спасибо. Он работает так же в Swift 4, я обновил ответ, чтобы отразить это. - person zeeshan; 15.04.2018
comment
Браво, сэр, браво - person Ryan Brodie; 10.10.2018

есть гораздо более простое решение:

- (UIImage *)tranlucentWithAlpha:(CGFloat)alpha
{
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [self drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:alpha];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
person Alexey Ishkov    schedule 07.11.2015
comment
Наверное, должен был быть принятый ответ. Самый быстрый / эффективный способ получить результат - person Will Von Ullrich; 14.12.2017

Привет, спасибо от пользователя 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);
person Nick Kovalsky    schedule 11.06.2017

Я понимаю, что это довольно поздно, но мне нужно было что-то вроде этого, поэтому я придумал быстрый и грязный метод, чтобы сделать это.

+ (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;
}
person Steven Veltema    schedule 08.05.2012
comment
Лучше имя setImage:withAlpha: - person Alexander; 25.05.2012
comment
set обычно относятся к свойствам, некоторым образом изменяя состояние получателя. лучше было бы назвать это image:withAlpha:? - person Jonathan.; 02.09.2012
comment
Ага. Также вызывающий набор применяет установку того же переданного объекта, а не возвращает новое изображение. - person some_id; 24.01.2014

такой же результат, как у других, другой стиль:

extension UIImage {

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

}
person Devin Pitcher    schedule 19.02.2020

Swift 5:

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

    draw(at: .zero, blendMode: .normal, alpha: alpha)
    return UIGraphicsGetImageFromCurrentImageContext()
  }
}
person Vadoff    schedule 21.06.2020

Если вы экспериментируете с рендерингом Metal и извлекаете CGImage, сгенерированный imageByApplyingAlpha в первом ответе, вы можете получить рендеринг Metal больше, чем вы ожидаете. Экспериментируя с 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 следует избегать масштабирования.

Надеюсь, такой ответ избавит новичков от лишнего раздражения.

person russes    schedule 30.03.2020