【问题标题】:UIImageView Is Blending Colors With No AlphaUIImageView 正在混合没有 Alpha 的颜色
【发布时间】:2021-12-10 08:42:38
【问题描述】:

我已经为此困扰了几天,找不到解决方案。我有一个透明背景的 UIImageView。它位于另一个视图之上(在示例中只是一个具有蓝色背景色的 UIView)。出于某种原因,即使它的 alpha 值为 0,它也会混合颜色(在这种情况下,全红色没有 alpha 值变成粉红色)。所需的输出是它会像没有 alpha 值的黑色一样清晰显示。

如果在白色上,它的行为符合预期(它是清晰的,并显示白色)。我尝试了不同的方法来创建 CGContext 和不同的 CALayer 混合模式,但无法让它不混合没有 alpha 值的颜色。

这里是一些复制问题的示例代码。

import UIKit
import PlaygroundSupport
import CoreGraphics

class MyViewController : UIViewController {
    var pixelPointer: UnsafeMutablePointer<UInt8>!
    
    let imageWidth = 20
    let imageHeight = 20
    
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .blue
        
        let viewSize: CGFloat = 150
        
        // Test Image
        pixelPointer  =  UnsafeMutablePointer<UInt8>.allocate(capacity: imageWidth * imageWidth * 4)
        let ctx  = CGContext(data: pixelPointer,
                             width: imageWidth,
                             height: imageHeight,
                             bitsPerComponent: 8,
                             bytesPerRow: 4 * imageWidth,
                             space: CGColorSpaceCreateDeviceRGB(),
                             bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
        for x in 0 ..< imageWidth {
            for y in 0 ..< imageHeight {
                if y == 7 || y == 8 || y == 9 {
                    // Red No Alpha -> Expected to be transparent
                    setColorFor(255, g: 0, b: 0, a: 0, x: x, y: y)
                } else if y == 10 || y == 11 || y == 12 {
                    // Black No Alpha -> Is transparent
                    setColorFor(0, g: 0, b: 0, a: 0, x: x, y: y)
                } else {
                    // Red
                    setColorFor(255, g: 0, b: 0, a: 255, x: x, y: y)
                }
                
            }
        }
        let cgImage = ctx.makeImage()!
        
        // ImageView with Clear Background
        let imageViewClearBackground = UIImageView()
        imageViewClearBackground.backgroundColor = .clear
        imageViewClearBackground.frame.origin = CGPoint(x: 10, y: 10)
        imageViewClearBackground.layer.borderColor = UIColor.black.cgColor
        imageViewClearBackground.layer.borderWidth = 1
        imageViewClearBackground.frame.size = CGSize(width: viewSize, height: viewSize)
        imageViewClearBackground.layer.magnificationFilter = CALayerContentsFilter.nearest
        
        imageViewClearBackground.image = UIImage(cgImage: cgImage)
        view.addSubview(imageViewClearBackground)
        
        // ImageView with White Background
        let imageViewWhiteBackground = UIImageView()
        imageViewWhiteBackground.layer.borderColor = UIColor.black.cgColor
        imageViewWhiteBackground.layer.borderWidth = 1
        imageViewWhiteBackground.backgroundColor = .white
        imageViewWhiteBackground.frame.size = CGSize(width: viewSize, height: viewSize)
        imageViewWhiteBackground.frame.origin = CGPoint(x: viewSize + 20, y: 10)
        imageViewWhiteBackground.layer.magnificationFilter = CALayerContentsFilter.nearest
        
        imageViewWhiteBackground.image = UIImage(cgImage: cgImage)
        view.addSubview(imageViewWhiteBackground)
        
        self.view = view
    }
    
    func setColorFor(_ r: Int, g: Int, b: Int, a: Int, x: Int, y: Int) {
        let offset = (y * Int(imageWidth) * 4) + x * 4
        pixelPointer[offset+0] = UInt8(r)
        pixelPointer[offset+1] = UInt8(g)
        pixelPointer[offset+2] = UInt8(b)
        pixelPointer[offset+3] = UInt8(a)
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

【问题讨论】:

    标签: swift colors uiimageview core-graphics


    【解决方案1】:

    问题是这样的:

    setColorFor(255, g: 0, b: 0, a: 0, x: x, y: y)
    

    不是有效的.premultipliedLast 颜色值。预乘意味着颜色已经乘以 alpha。如果将 255 乘以 0,则得到 0,因此 that 是此处正确的红色值 — 正如第 10-12 行的结果所示。

    如果您只是使用 UIGraphicsImageRenderer 以正常方式而不是原始位图上下文来构建图像,您可能会少很多困惑。但是当然,如​​果您的用例排除了这种情况,那么请务必使用位图 - 但是您有更多的空间可以不正确地使用它。

    【讨论】:

    • 谢谢马特。问题似乎正如您所指出的那样。由于上下文的创建方式,我需要预先乘以这些值。不幸的是,对于我的用例来说,构建图像的“正常”方式是不可能的。感谢您让我朝着正确的方向前进。
    • 没问题。感谢您提出如此结构合理的问题。
    猜你喜欢
    • 1970-01-01
    • 2018-12-12
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    相关资源
    最近更新 更多