ios - 使用 UIGraphicImageRenderer 的 CGContext 重绘图像,翻转图像。如何防止翻转?
问题描述
给定一个图像,当我想转换为标准 sRGB 时,我可以 CGContext 来帮助绘制它,如下所示。
给定原始图像
当我CGContext
直接使用时,它会正确重绘
extension UIImage {
func toSRGB() -> UIImage {
guard let cgImage = cgImage,
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB),
let cgContext = CGContext(
data: nil,
width: Int(size.width),
height: Int(size.height),
bitsPerComponent: 8,
bytesPerRow: 0,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
else { return self }
cgContext.draw(cgImage, in: CGRect(origin: .zero, size: size))
guard let newCGImage = cgContext.makeImage()
else { return self }
return UIImage.init(cgImage: newCGImage)
}
}
但是,如果我使用CGContext
fromUIGraphicImageRenderer
extension UIImage {
func toSRGB() -> UIImage {
guard let cgImage = cgImage else { return self }
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { ctx in
ctx.cgContext.draw(cgImage, in: CGRect(origin: .zero, size: size))
}
}
}
图像被颠倒如下。为什么它被翻转了,我怎样才能避免翻转?
解决方案
无需获取 cgImage。你可以简单地绘制 UIImage:
extension UIImage {
func toSRGB() -> UIImage {
UIGraphicsImageRenderer(size: size).image { _ in
draw(in: CGRect(origin: .zero, size: size))
}
}
}
图像翻转的原因是UIKit 和 Quartz 中的坐标系之间的差异。UIKit 垂直原点在顶部,而 Quartz 垂直原点在底部。解决此问题的最简单方法是应用 CGAffineTransform 将其缩放减一,然后将高度距离向后平移:
extension CGAffineTransform {
static func flippingVerticaly(_ height: CGFloat) -> CGAffineTransform {
var transform = CGAffineTransform(scaleX: 1, y: -1)
transform = transform.translatedBy(x: 0, y: -height)
return transform
}
}
extension UIImage {
func toSRGB() -> UIImage {
guard let cgImage = cgImage else { return self }
return UIGraphicsImageRenderer(size: size).image { ctx in
ctx.cgContext.concatenate(.flippingVerticaly(size.height))
ctx.cgContext.draw(cgImage, in: CGRect(origin: .zero, size: size))
}
}
}
编辑/更新:
要将比例保持在 1x,您可以传递图像渲染器格式:
extension UIImage {
func toSRGB() -> UIImage {
guard let cgImage = cgImage else { return self }
let format = imageRendererFormat
format.scale = 1
return UIGraphicsImageRenderer(size: size, format: format).image { ctx in
ctx.cgContext.concatenate(.flippingVerticaly(size.height))
ctx.cgContext.draw(cgImage, in: CGRect(origin: .zero, size: size))
}
}
}
推荐阅读
- python - 关于python3导入包的问题
- javascript - 如何将 require/import 视为一个值而不是依赖项
- apache-spark - Pyspark:如何从 Weeknumber 和 Year 获取日期
- jquery - 多次调用 play() 不会触发
- xml - Xslt在通过xsl文件解析时为负值添加括号'()'作为响应
- spring - Spring 缓存如何返回修改后的对象?
- python - 检查输入时出错:预期 lstm_1_input 有 3 个维度,但得到了形状为 (5, 3) 的数组
- c - Linux Networking:RTP 序列号不递增
- reactjs - 如何以编程方式更新 antd 中的表单字段值
- sql - 获取/使用新记录的自动增量主键作为另一个表中记录的外键