裁剪 CIImage
Cropping CIImage
我有一个 class,它接受一个 UIImage
,用它初始化一个 CIImage
,就像这样:
workingImage = CIImage.init(image: baseImage!)
然后使用该图像以 3x3 的模式从中裁剪出 9 个相邻的正方形 - 在一个循环中:
for x in 0..<3
{
for y in 0..<3
{
croppingRect = CGRect(x: CGFloat(Double(x) * sideLength + startPointX),
y: CGFloat(Double(y) * sideLength + startPointY),
width: CGFloat(sideLength),
height: CGFloat(sideLength))
let tmpImg = (workingImage?.cropping(to: croppingRect))!
}
}
那些 tmpImgs 被插入到 table 中并稍后使用,但这不是重点。
此代码适用于 IOS 9
和 IOS 10
模拟器,但 不适用于 实际 IOS 10设备。生成的图像要么全是空的,要么其中一个像它应该是的一半,其余的又是空的。
这不是应该在 IOS 10
中完成的吗?
问题的核心是通过CIImage 不是裁剪UIImage 的方式。一方面,从 CIImage 回到 UIImage 是一件复杂的事情。另一方面,整个往返是不必要的。
如何裁剪
要裁剪图像,请制作所需裁剪大小的图像图形上下文,然后在 UIImage 上调用 draw(at:)
以在相对于图形上下文的所需点绘制它,以便所需的部分图像落入上下文。现在提取生成的新图像并关闭上下文。
为了演示,我将裁剪到您要裁剪到的三分之一中的 一个 ,即右下三分之一:
let sz = baseImage.size
UIGraphicsBeginImageContextWithOptions(
CGSize(width:sz.width/3.0, height:sz.height/3.0),
false, 0)
baseImage.draw(at:CGPoint(x: -sz.width/3.0*2.0, y: -sz.height/3.0*2.0))
let tmpImg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
原图(baseImage
):
裁剪图像(tmpImg
):
其他部分完全平行
Core Image的坐标系与UIKit不匹配,需要镜像rect。
因此在您的特定情况下,您需要:
var ciRect = croppingRect
ciRect.origin.y = workingImage!.extent.height - ciRect.origin.y - ciRect.height
let tmpImg = workingImage!.cropped(to: ciRect)
这绝对适用于 iOS 10+。
在更一般的情况下,我们将制作一个涵盖两种可能坐标系的 UIImage 扩展,这比 draw(at:)
:
快得多
extension UIImage {
/// Return a new image cropped to a rectangle.
/// - parameter rect:
/// The rectangle to crop.
open func cropped(to rect: CGRect) -> UIImage {
// a UIImage is either initialized using a CGImage, a CIImage, or nothing
if let cgImage = self.cgImage {
// CGImage.cropping(to:) is magnitudes faster than UIImage.draw(at:)
if let cgCroppedImage = cgImage.cropping(to: rect) {
return UIImage(cgImage: cgCroppedImage)
} else {
return UIImage()
}
}
if let ciImage = self.ciImage {
// Core Image's coordinate system mismatch with UIKit, so rect needs to be mirrored.
var ciRect = rect
ciRect.origin.y = ciImage.extent.height - ciRect.origin.y - ciRect.height
let ciCroppedImage = ciImage.cropped(to: ciRect)
return UIImage(ciImage: ciCroppedImage)
}
return self
}
}
我已经为它制作了一个pod,所以源代码在https://github.com/Coeur/ImageEffects/blob/master/SwiftImageEffects/ImageEffects%2Bextensions.swift
我有一个 class,它接受一个 UIImage
,用它初始化一个 CIImage
,就像这样:
workingImage = CIImage.init(image: baseImage!)
然后使用该图像以 3x3 的模式从中裁剪出 9 个相邻的正方形 - 在一个循环中:
for x in 0..<3
{
for y in 0..<3
{
croppingRect = CGRect(x: CGFloat(Double(x) * sideLength + startPointX),
y: CGFloat(Double(y) * sideLength + startPointY),
width: CGFloat(sideLength),
height: CGFloat(sideLength))
let tmpImg = (workingImage?.cropping(to: croppingRect))!
}
}
那些 tmpImgs 被插入到 table 中并稍后使用,但这不是重点。
此代码适用于 IOS 9
和 IOS 10
模拟器,但 不适用于 实际 IOS 10设备。生成的图像要么全是空的,要么其中一个像它应该是的一半,其余的又是空的。
这不是应该在 IOS 10
中完成的吗?
问题的核心是通过CIImage 不是裁剪UIImage 的方式。一方面,从 CIImage 回到 UIImage 是一件复杂的事情。另一方面,整个往返是不必要的。
如何裁剪
要裁剪图像,请制作所需裁剪大小的图像图形上下文,然后在 UIImage 上调用 draw(at:)
以在相对于图形上下文的所需点绘制它,以便所需的部分图像落入上下文。现在提取生成的新图像并关闭上下文。
为了演示,我将裁剪到您要裁剪到的三分之一中的 一个 ,即右下三分之一:
let sz = baseImage.size
UIGraphicsBeginImageContextWithOptions(
CGSize(width:sz.width/3.0, height:sz.height/3.0),
false, 0)
baseImage.draw(at:CGPoint(x: -sz.width/3.0*2.0, y: -sz.height/3.0*2.0))
let tmpImg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
原图(baseImage
):
裁剪图像(tmpImg
):
其他部分完全平行
Core Image的坐标系与UIKit不匹配,需要镜像rect。
因此在您的特定情况下,您需要:
var ciRect = croppingRect
ciRect.origin.y = workingImage!.extent.height - ciRect.origin.y - ciRect.height
let tmpImg = workingImage!.cropped(to: ciRect)
这绝对适用于 iOS 10+。
在更一般的情况下,我们将制作一个涵盖两种可能坐标系的 UIImage 扩展,这比 draw(at:)
:
extension UIImage {
/// Return a new image cropped to a rectangle.
/// - parameter rect:
/// The rectangle to crop.
open func cropped(to rect: CGRect) -> UIImage {
// a UIImage is either initialized using a CGImage, a CIImage, or nothing
if let cgImage = self.cgImage {
// CGImage.cropping(to:) is magnitudes faster than UIImage.draw(at:)
if let cgCroppedImage = cgImage.cropping(to: rect) {
return UIImage(cgImage: cgCroppedImage)
} else {
return UIImage()
}
}
if let ciImage = self.ciImage {
// Core Image's coordinate system mismatch with UIKit, so rect needs to be mirrored.
var ciRect = rect
ciRect.origin.y = ciImage.extent.height - ciRect.origin.y - ciRect.height
let ciCroppedImage = ciImage.cropped(to: ciRect)
return UIImage(ciImage: ciCroppedImage)
}
return self
}
}
我已经为它制作了一个pod,所以源代码在https://github.com/Coeur/ImageEffects/blob/master/SwiftImageEffects/ImageEffects%2Bextensions.swift