我正在使用此扩展名来获取像素颜色:
extension UIImage {
subscript (x: Int, y: Int) -> UIColor? {
guard x >= 0 && x < Int(size.width) && y >= 0 && y < Int(size.height),
let cgImage = cgImage,
let provider = cgImage.dataProvider,
let providerData = provider.data,
let data = CFDataGetBytePtr(providerData) else {
return nil
}
let numberOfComponents = 4
let pixelData = ((Int(size.width) * y) + x) * numberOfComponents
let r = CGFloat(data[pixelData]) / 255.0
let g = CGFloat(data[pixelData + 1]) / 255.0
let b = CGFloat(data[pixelData + 2]) / 255.0
let a = CGFloat(data[pixelData + 3]) / 255.0
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
使用操场或模拟器运行时,一切正常,但是在设备(iPhone XR)上运行时,我得到了不同的值。
经过一段时间的调试,我发现当我使用模拟器时,cgimage具有alphaInfo kCGImageAlphaLast,而当我使用设备时,alphaInfo是kCGImageAlphaNoneSkipLast
调试:
// Simulator
<CGImage 0x7f9f674150f0> (IP)
<<CGColorSpace 0x600002893120> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
width = 1000, height = 500, bpc = 8, bpp = 32, row bytes = 4000
kCGImageAlphaLast | 0 (default byte order) | kCGImagePixelFormatPacked
is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes
// -------------------------------------------- //
// Device
<CGImage 0x7f88df70d980> (DP)
<<CGColorSpace 0x6000003dc540> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
width = 1000, height = 500, bpc = 8, bpp = 32, row bytes = 4000
kCGImageAlphaNoneSkipLast | 0 (default byte order) | kCGImagePixelFormatPacked
is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes
由于alphaInfo是只读属性,因此有任何方法可以设置该属性或重新创建将alphaValue设置为
kCGImageAlphaLast
的方法。我发现该颜色值乘以alpha值,但是我有点困惑如何“恢复”“正确”值。
https://developer.apple.com/documentation/coregraphics/cgimagealphainfo/kcgimagealphapremultipliedlast
最佳答案
您需要创建一个不透明的图像上下文,设置其alpha值并将原始图像绘制到此新上下文中:
extension UIImage {
func applying(alpha: CGFloat) -> UIImage? {
guard let cgImage = self.cgImage else { return nil }
// For iOS10 or later you can use UIGraphicsImageRenderer
if #available(iOS 10, *) {
let format = imageRendererFormat
format.opaque = false
return UIGraphicsImageRenderer(size: size, format: format).image { context in
context.cgContext.scaleBy(x: 1, y: -1)
context.cgContext.translateBy(x: .zero, y: -size.height)
context.cgContext.setBlendMode(.multiply)
context.cgContext.setAlpha(alpha)
context.cgContext.draw(cgImage, in: .init(origin: .zero, size: size))
}
} else {
// For older iOS versions you need to use UIGraphicsBeginImageContextWithOptions
UIGraphicsBeginImageContextWithOptions(size, false, scale)
defer { UIGraphicsEndImageContext() }
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.scaleBy(x: 1, y: -1)
context.translateBy(x: .zero, y: -size.height)
context.setBlendMode(.multiply)
context.setAlpha(alpha)
context.draw(cgImage, in: .init(origin: .zero, size: size))
return UIGraphicsGetImageFromCurrentImageContext()
}
}
}
let image = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!
let transparentImage = image.applying(alpha: 0.5)