【问题标题】:How to set the opacity/alpha of a UIImage?如何设置 UIImage 的不透明度/alpha?
【发布时间】:2011-07-02 08:58:37
【问题描述】:

我知道你可以用 UIImageView 做到这一点,但它可以做到 UIImage 吗?我想让 UIImageView 的动画图像数组属性成为相同图像但具有不同不透明度的数组。想法?

【问题讨论】:

    标签: ios uiimageview uiimage opacity alpha


    【解决方案1】:

    我只是需要这样做,但认为 Steven 的解决方案会很慢。这应该希望使用图形硬件。在 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;
    }
    

    【讨论】:

    • 不记得为什么我需要这个:)
    • 很好的解决方案!谢谢你尼克!
    • 请确保您在主线程上调用 UIGraphicsBeginImageContextWithOptions,因为后台渲染将是不可预测的。
    • 根据 Apple 的说法,您可以在 iOS 4 及更高版本之后的任何线程上调用 UIGraphicsBeginImageContextWithOptions。
    • 效果很好,非常感谢。对于 iOS 开发的其他新手,这里是为 UIImage 创建类别的步骤。 1. 右键单击​​项目的主管并选择新建文件。 2. 在出现的屏幕中,选择Objective-C 类别文件类型。 3. 在 .m 文件中添加答案代码,在 .h 文件中添加方法声明。 4.在使用图片透明的文件中,#import该文件。 5. 在 UIImage 的实例上使用 imageByApplyingAlpha 方法。
    【解决方案2】:

    设置其显示的视图的不透明度。

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

    在动画中使用它。您可以在一段时间内更改动画中的 alpha。

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

    【讨论】:

    • 是的,我在想我可能必须像这样使用计时器来不断更改不透明度,只是认为为动画图像数组属性设置一个数组会容易得多,这样它就会动画靠自己。
    • 您可以使用动画代理像心跳一样“输入”和“输出”动画。不要使用计时器,动画会平滑地更改 alpha。祝你好运。
    • 这仅适用于开发人员使用 UIImageView 的情况。这个问题清楚地表明情况并非如此。
    • 这适用于 CALayer 中呈现的 UIImage,只有您设置 layer.opacity 而无需修改图像。谢谢垫子!
    • 太棒了!在 UIButton 上工作,正是我需要的。
    【解决方案3】:

    基于 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 或不是使用 UIGraphicsBeginImageContext 创建的,则此值可能为 nil。

    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 版本。
    • 谢谢。它在 Swift 4 中的工作原理相同,我更新了答案以反映这一点。
    • 好样的先生,好样的
    【解决方案4】:

    有更简单的解决方案:

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

    【讨论】:

    • 可能应该是公认的答案。获得结果的最快/最有效方式
    【解决方案5】:

    嘿嘿感谢 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);
    

    【讨论】:

      【解决方案6】:

      我意识到这已经很晚了,但我需要这样的东西,所以我想出了一个快速而肮脏的方法来做到这一点。

      + (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;
      }
      

      【讨论】:

      • 更好的名字是setImage:withAlpha:
      • set 通常是指属性,以某种方式改变接收者的状态。最好把它命名为image:withAlpha:?
      • 是的。同样调用 set 应用设置传入的相同对象,而不是返回新图像。
      【解决方案7】:

      斯威夫特 5:

      extension UIImage {
        func withAlphaComponent(_ alpha: CGFloat) -> UIImage? {
          UIGraphicsBeginImageContextWithOptions(size, false, scale)
          defer { UIGraphicsEndImageContext() }
      
          draw(at: .zero, blendMode: .normal, alpha: alpha)
          return UIGraphicsGetImageFromCurrentImageContext()
        }
      }
      

      【讨论】:

        【解决方案8】:

        结果和别人一样,风格不同:

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

        【讨论】:

          【解决方案9】:

          如果您正在尝试使用 Metal 渲染并且您在第一个回复中提取由 imageByApplyingAlpha 生成的 CGImage,那么您最终可能会得到比您预期更大的 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 应该可以避免任何缩放。

          希望这个回复可以为初学者省去很多麻烦。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-18
            • 2014-12-29
            • 2011-02-19
            • 1970-01-01
            • 1970-01-01
            • 2012-11-24
            相关资源
            最近更新 更多