从alpha +背景计算不透明的颜色?

时间:2015-11-08 12:02:50

标签: ios

我想"减轻"通过对其应用0.3的α来获得某种颜色。这显示在白色背景上。

我想确定与白色背景上显示的这种半透明颜色相对应的不透明颜色。原因是我使用它作为视图控制器的背景颜色,当这个背景是半透明时,转换看起来很糟糕。

我没有尝试过任何东西,因为我不知道采用合理的方法来解决这个问题,除非拍摄快照并获得它的颜色,但这似乎有点过分。无法找到任何信息,搜索结果会被"如何制作背景半透明"等

编辑:将imataptool的答案部分(以及移植到Swift)放在一起,这就是我想出的:

extension UIColor {

    static func opaqueColorByDisplayingTransparentColorOnBackground(transparentColor: UIColor, backgroundColor: UIColor) -> UIColor {

        let bgView = UIView(frame: CGRectMake(0, 0, 1, 1))
        bgView.backgroundColor = backgroundColor
        let overlayView = UIView(frame: CGRectMake(0, 0, 1, 1))
        overlayView.backgroundColor = transparentColor
        bgView.addSubview(overlayView)

        let image = UIView.imageWithView(bgView)

        let provider = CGImageGetDataProvider(image.CGImage)
        let pixelData = CGDataProviderCopyData(provider)
        let data = CFDataGetBytePtr(pixelData)

        return UIColor(
            red: CGFloat(data[0]) / 255.0,
            green: CGFloat(data[1]) / 255.0,
            blue: CGFloat(data[2]) / 255.0,
            alpha: 1
        )
    }
}

extension UIView {

    // src http://stackoverflow.com/a/32042439/930450
    class func imageWithView(view: UIView) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
        view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img
    }
}

2 个答案:

答案 0 :(得分:1)

编辑1:这并不是说这是实现特定目标的最佳方式,但它确实解决了获得具有特定不透明度的两种颜色混合的RGB的问题。您没有提供足够的信息,说明您正在为我做些什么来提供更具体的答案。但是,如果此解决方案能够以可接受的性能执行您所需的操作,那么就可以使用它。

编辑2:有关将UIView渲染为iOS 7中的位图的新(ish)方法,请参阅this Q&A(因此,如果您支持iOS 6,则可以忽略这一点,但这不太可能)。这篇文章的要点是你现在可以使用UIView方法 -drawViewHierarchyInRect:(CGRect)afterScreenUpdates:(BOOL)

我不能说是否存在计算确切答案的数学方法,但实现这一目标的一种方法是:

  1. 将两个视图添加到父视图(透明视图下方的不透明视图)
  2. 将父视图(及其所有子视图)转换为UIImage
  3. 对UIImage的颜色进行采样
  4. 做1是微不足道的。你可以用

    做2
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return img;
    

    现在img包含您想要的颜色的图像。现在你只需要弄清楚它是由什么颜色组成的。我相信你可以使用this answer中提供的代码来做到这一点。为方便起见,我会将其复制到此处。

    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    const UInt8* data = CFDataGetBytePtr(pixelData);
    
    int pixelInfo = ((image.size.width  * y) + x ) * 4; // The image is png
    
    UInt8 red = data[pixelInfo];         // If you need this info, enable it
    UInt8 green = data[(pixelInfo + 1)]; // If you need this info, enable it
    UInt8 blue = data[pixelInfo + 2];    // If you need this info, enable itgame
    CFRelease(pixelData);
    

    redgreenblue现在包含您在视图中选择的任何点的颜色的RGB值。你可能只是去它的中间。 此外,为了提高此过程的效果,您可以选择仅对相关视图的一小部分进行成像(可能只有一个像素)。

答案 1 :(得分:0)

如果有人会寻找更简单的解决方案,那么此post about combining colors applying specific alpha可能会有所帮助。

TLDR

extension UIColor {

    func combine(with color: UIColor, amount: CGFloat) -> UIColor {

        let fromComponents = components()
        let toComponents = color.components()

        let redAmount = lerp(
            from:  fromComponents.red,
            to:    toComponents.red,
            alpha: amount
        )
        let greenAmount = lerp(
            from:  fromComponents.green,
            to:    toComponents.green,
            alpha: amount
        )
        let blueAmount = lerp(
            from:  fromComponents.blue,
            to:    toComponents.blue,
            alpha: amount
        )

        return UIColor(
            red:   redAmount,
            green: greenAmount,
            blue:  blueAmount,
            alpha: 1
        )
    }

    func components() -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {

        var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
        getRed(&r, green: &g, blue: &b, alpha: &a)

        return (r, g, b, a)
    }
}

func lerp(from a: CGFloat, to b: CGFloat, alpha: CGFloat) -> CGFloat {
    return (1 - alpha) * a + alpha * b
}