swift 2.0 之后的 CGBitmapInfo alpha 掩码
CGBitmapInfo alpha mask after swift 2.0
我正在使用此 github 存储库 https://github.com/Haneke/HanekeSwift 中的库来缓存从服务器下载的图像。更新到 swift 2.0 后,一切都搞砸了。
除了这个功能,我已经能够修复所有问题:
func hnk_decompressedImage() -> UIImage! {
let originalImageRef = self.CGImage
let originalBitmapInfo = CGImageGetBitmapInfo(originalImageRef)
let alphaInfo = CGImageGetAlphaInfo(originalImageRef)
// See:
var bitmapInfo = originalBitmapInfo
switch (alphaInfo) {
case .None:
bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
case .PremultipliedFirst, .PremultipliedLast, .NoneSkipFirst, .NoneSkipLast:
break
case .Only, .Last, .First: // Unsupported
return self
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let pixelSize = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale)
if let context = CGBitmapContextCreate(nil, Int(ceil(pixelSize.width)), Int(ceil(pixelSize.height)), CGImageGetBitsPerComponent(originalImageRef), 0, colorSpace, bitmapInfo) {
let imageRect = CGRectMake(0, 0, pixelSize.width, pixelSize.height)
UIGraphicsPushContext(context)
// Flip coordinate system. See:
CGContextTranslateCTM(context, 0, pixelSize.height)
CGContextScaleCTM(context, 1.0, -1.0)
// UIImage and drawInRect takes into account image orientation, unlike CGContextDrawImage.
self.drawInRect(imageRect)
UIGraphicsPopContext()
let decompressedImageRef = CGBitmapContextCreateImage(context)
let scale = UIScreen.mainScreen().scale
let image = UIImage(CGImage: decompressedImageRef, scale:scale, orientation:UIImageOrientation.Up)
return image
} else {
return self
}
}
具体来说,这是抛出错误的代码行:
bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
错误:一元运算符“~”不能应用于 CGBitmapInfo 类型的操作数
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
错误:二元运算符“|=”不能应用于 'CGBitmapInfo'
类型的操作数
if let context = CGBitmapContextCreate(nil, Int(ceil(pixelSize.width)), Int(ceil(pixelSize.height)), CGImageGetBitsPerComponent(originalImageRef), 0, colorSpace, bitmapInfo)
错误:无法将 'CGBitmapInfo' 类型的值转换为 UInt32
类型的预期参数
错误:无法将 'CGBitmapInfo' 类型的值转换为 UInt32
类型的预期参数
Swift 2.0实际上需要一个UInt32而不是CGBitMapInfo对象,所以你应该在CGBitMapInfo中取出一个UInt32变量。
CGBitmapContextCreate(
nil,
Int(ceil(pixelSize.width)),
Int(ceil(pixelSize.height)),
CGImageGetBitsPerComponent(originalImageRef),
0,
colorSpace,
bitmapInfo.rawValue)
OptionSetType
在 swift 2 CGBitmapInfo 是一个 OptionSetType。要初始化一个,您可以遵循约定
/// static let Box = PackagingOptions(rawValue: 1)
/// static let Carton = PackagingOptions(rawValue: 2)
/// static let Bag = PackagingOptions(rawValue: 4)
/// static let Satchel = PackagingOptions(rawValue: 8)
/// static let BoxOrBag: PackagingOptions = [Box, Bag]
/// static let BoxOrCartonOrBag: PackagingOptions = [Box, Carton, Bag]
对于 CGBitmapInfo,它是 OptionSetTypes 的 OptionSetType
public enum CGImageAlphaInfo : UInt32 {
case None /* For example, RGB. */
case PremultipliedLast /* For example, premultiplied RGBA */
case PremultipliedFirst /* For example, premultiplied ARGB */
case Last /* For example, non-premultiplied RGBA */
case First /* For example, non-premultiplied ARGB */
case NoneSkipLast /* For example, RBGX. */
case NoneSkipFirst /* For example, XRGB. */
case Only /* No color data, alpha data only */
}
@available(iOS 2.0, *)
public struct CGBitmapInfo : OptionSetType {
public init(rawValue: UInt32)
public static var AlphaInfoMask: CGBitmapInfo { get }
public static var FloatComponents: CGBitmapInfo { get }
public static var ByteOrderMask: CGBitmapInfo { get }
public static var ByteOrderDefault: CGBitmapInfo { get }
public static var ByteOrder16Little: CGBitmapInfo { get }
public static var ByteOrder32Little: CGBitmapInfo { get }
public static var ByteOrder16Big: CGBitmapInfo { get }
public static var ByteOrder32Big: CGBitmapInfo { get }
}
如何使用字节顺序和 alpha 掩码设置对其进行初始化的示例:
let bitmapInfo:CGBitmapInfo = [.ByteOrder32Little, CGBitmapInfo(rawValue: ~CGBitmapInfo.AlphaInfoMask.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue)]
related question, answer and comment
我正在使用此 github 存储库 https://github.com/Haneke/HanekeSwift 中的库来缓存从服务器下载的图像。更新到 swift 2.0 后,一切都搞砸了。
除了这个功能,我已经能够修复所有问题:
func hnk_decompressedImage() -> UIImage! {
let originalImageRef = self.CGImage
let originalBitmapInfo = CGImageGetBitmapInfo(originalImageRef)
let alphaInfo = CGImageGetAlphaInfo(originalImageRef)
// See:
var bitmapInfo = originalBitmapInfo
switch (alphaInfo) {
case .None:
bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
case .PremultipliedFirst, .PremultipliedLast, .NoneSkipFirst, .NoneSkipLast:
break
case .Only, .Last, .First: // Unsupported
return self
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let pixelSize = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale)
if let context = CGBitmapContextCreate(nil, Int(ceil(pixelSize.width)), Int(ceil(pixelSize.height)), CGImageGetBitsPerComponent(originalImageRef), 0, colorSpace, bitmapInfo) {
let imageRect = CGRectMake(0, 0, pixelSize.width, pixelSize.height)
UIGraphicsPushContext(context)
// Flip coordinate system. See:
CGContextTranslateCTM(context, 0, pixelSize.height)
CGContextScaleCTM(context, 1.0, -1.0)
// UIImage and drawInRect takes into account image orientation, unlike CGContextDrawImage.
self.drawInRect(imageRect)
UIGraphicsPopContext()
let decompressedImageRef = CGBitmapContextCreateImage(context)
let scale = UIScreen.mainScreen().scale
let image = UIImage(CGImage: decompressedImageRef, scale:scale, orientation:UIImageOrientation.Up)
return image
} else {
return self
}
}
具体来说,这是抛出错误的代码行:
bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
错误:一元运算符“~”不能应用于 CGBitmapInfo 类型的操作数
bitmapInfo |= CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
错误:二元运算符“|=”不能应用于 'CGBitmapInfo'
类型的操作数if let context = CGBitmapContextCreate(nil, Int(ceil(pixelSize.width)), Int(ceil(pixelSize.height)), CGImageGetBitsPerComponent(originalImageRef), 0, colorSpace, bitmapInfo)
错误:无法将 'CGBitmapInfo' 类型的值转换为 UInt32
类型的预期参数错误:无法将 'CGBitmapInfo' 类型的值转换为 UInt32
类型的预期参数Swift 2.0实际上需要一个UInt32而不是CGBitMapInfo对象,所以你应该在CGBitMapInfo中取出一个UInt32变量。
CGBitmapContextCreate(
nil,
Int(ceil(pixelSize.width)),
Int(ceil(pixelSize.height)),
CGImageGetBitsPerComponent(originalImageRef),
0,
colorSpace,
bitmapInfo.rawValue)
OptionSetType 在 swift 2 CGBitmapInfo 是一个 OptionSetType。要初始化一个,您可以遵循约定
/// static let Box = PackagingOptions(rawValue: 1)
/// static let Carton = PackagingOptions(rawValue: 2)
/// static let Bag = PackagingOptions(rawValue: 4)
/// static let Satchel = PackagingOptions(rawValue: 8)
/// static let BoxOrBag: PackagingOptions = [Box, Bag]
/// static let BoxOrCartonOrBag: PackagingOptions = [Box, Carton, Bag]
对于 CGBitmapInfo,它是 OptionSetTypes 的 OptionSetType
public enum CGImageAlphaInfo : UInt32 {
case None /* For example, RGB. */
case PremultipliedLast /* For example, premultiplied RGBA */
case PremultipliedFirst /* For example, premultiplied ARGB */
case Last /* For example, non-premultiplied RGBA */
case First /* For example, non-premultiplied ARGB */
case NoneSkipLast /* For example, RBGX. */
case NoneSkipFirst /* For example, XRGB. */
case Only /* No color data, alpha data only */
}
@available(iOS 2.0, *)
public struct CGBitmapInfo : OptionSetType {
public init(rawValue: UInt32)
public static var AlphaInfoMask: CGBitmapInfo { get }
public static var FloatComponents: CGBitmapInfo { get }
public static var ByteOrderMask: CGBitmapInfo { get }
public static var ByteOrderDefault: CGBitmapInfo { get }
public static var ByteOrder16Little: CGBitmapInfo { get }
public static var ByteOrder32Little: CGBitmapInfo { get }
public static var ByteOrder16Big: CGBitmapInfo { get }
public static var ByteOrder32Big: CGBitmapInfo { get }
}
如何使用字节顺序和 alpha 掩码设置对其进行初始化的示例:
let bitmapInfo:CGBitmapInfo = [.ByteOrder32Little, CGBitmapInfo(rawValue: ~CGBitmapInfo.AlphaInfoMask.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue)]
related question, answer and comment