如何为显示 CIImage 的 GLKView 实现 contentMode?
How to implement contentMode for GLKView displaying a CIImage?
我创建了一个 GLKView
子类来显示 CIImage
,以便更好地显示 CIFilter
链的输出图像。
但是,我似乎需要实施 contentMode
逻辑,以便在 drawRect(rect: CGRect)
调用中为 drawImage(image: CIImage, inRect: CGRect, fromRect: CGRect)
提供正确的 inRect
。
有人知道如何实现这样的逻辑以符合 UIImageView 的 contentMode
行为吗?
在iOS10.3中contentMode的设置好像没有影响到glkView。
看起来总是bottomLeft模式。
为了使 glkView 以可查看的格式显示 CIImage,这对我有用。
在glkView(_view: GLKView, drawIn rect: CGRect)中传入的rect需要修改view的contentScaleFactor
此代码假定您已经在 GLKViewController 的 viewDidLoad 方法中初始化了 EAGLContext(我的 glkView 名为 effectView2)
context = EAGLContext.init(api: EAGLRenderingAPI.openGLES2)
if context != nil {
effectView2.context = self.context!
EAGLContext.setCurrent(self.context)
ciContext = CIContext.init(eaglContext: context!)
设置glkView后设置比例因子
myScaleFactor = view.contentScaleFactor
在你的 glkView(_ view: GLKView, drawIn rect: CGRect) 中这样做
let adjustedRect = CGRect(x: 0.0, y: 0.0, width: rect.width * myScaleFactor, height: rect.height * myScaleFactor )
然后用你的ciContext在adjustedRect中绘制ciImage。像这样使用 ciImage 的范围作为 from 参数:
ciContext!.draw(outputImage, in: adjustedRect , from: (ciSourceImage?.extent)!)
- 哦,是的。我假设您已经找到了调整 GLKView 比例因子的技术说明。它在您的 GLKView 子类中调用一行。参见 https://developer.apple.com/library/content/qa/qa1909/_index.html
您很可能需要对这种方法进行一些调整。我目前正在处理不同源 ciImages 的方向更改问题。
我花了很长时间才找到这么多所以我想分享这些发现..
请 post 您发现的任何改进!
希望对您有所帮助
威尔L-B
使 contentMode 以与 UIView 类似的方式工作。我做了以下 class.
final class ContenModeEnforcer {
static func rectFor(contentMode: UIViewContentMode, fromRect: CGRect, toRect: CGRect) -> CGRect {
switch contentMode {
case .scaleToFill:
return toRect
case .scaleAspectFit:
return aspectFit(fromRect, toRect: toRect)
case .scaleAspectFill:
return aspectFill(fromRect, toRect: toRect)
case .redraw:
return fromRect
case .center:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .top:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .bottom:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
case .left:
let origin = CGPoint(
x: 0.0,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .right:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .topLeft:
let origin = CGPoint(
x: 0.0,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .topRight:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .bottomLeft:
let origin = CGPoint(
x: 0.0,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
case .bottomRight:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
}
}
static fileprivate func aspectFit(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
let fromAspectRatio = fromRect.size.width / fromRect.size.height;
let toAspectRatio = toRect.size.width / toRect.size.height;
var fitRect = toRect
if (fromAspectRatio > toAspectRatio) {
fitRect.size.height = toRect.size.width / fromAspectRatio;
fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
} else {
fitRect.size.width = toRect.size.height * fromAspectRatio;
fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
}
return fitRect.integral
}
static fileprivate func aspectFill(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
let fromAspectRatio = fromRect.size.width / fromRect.size.height;
let toAspectRatio = toRect.size.width / toRect.size.height;
var fitRect = toRect
if (fromAspectRatio > toAspectRatio) {
fitRect.size.width = toRect.size.height * fromAspectRatio;
fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
} else {
fitRect.size.height = toRect.size.width / fromAspectRatio;
fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
}
return fitRect.integral
}
}
在抽奖中(_:CGRect).
let inputBounds = image.extent
let drawableBounds = CGRect(x: 0, y: 0, width: self.drawableWidth, height: self.drawableHeight)
let targetBounds = ContenModeEnforcer.rectFor(contentMode: contentMode, fromRect: inputBounds, toRect: drawableBounds)
ciContext.draw(image, in: targetBounds, from: inputBounds)
我创建了一个 GLKView
子类来显示 CIImage
,以便更好地显示 CIFilter
链的输出图像。
但是,我似乎需要实施 contentMode
逻辑,以便在 drawRect(rect: CGRect)
调用中为 drawImage(image: CIImage, inRect: CGRect, fromRect: CGRect)
提供正确的 inRect
。
有人知道如何实现这样的逻辑以符合 UIImageView 的 contentMode
行为吗?
在iOS10.3中contentMode的设置好像没有影响到glkView。 看起来总是bottomLeft模式。
为了使 glkView 以可查看的格式显示 CIImage,这对我有用。
在glkView(_view: GLKView, drawIn rect: CGRect)中传入的rect需要修改view的contentScaleFactor
此代码假定您已经在 GLKViewController 的 viewDidLoad 方法中初始化了 EAGLContext(我的 glkView 名为 effectView2)
context = EAGLContext.init(api: EAGLRenderingAPI.openGLES2) if context != nil { effectView2.context = self.context! EAGLContext.setCurrent(self.context) ciContext = CIContext.init(eaglContext: context!)
设置glkView后设置比例因子
myScaleFactor = view.contentScaleFactor
在你的 glkView(_ view: GLKView, drawIn rect: CGRect) 中这样做
let adjustedRect = CGRect(x: 0.0, y: 0.0, width: rect.width * myScaleFactor, height: rect.height * myScaleFactor )
然后用你的ciContext在adjustedRect中绘制ciImage。像这样使用 ciImage 的范围作为 from 参数:
ciContext!.draw(outputImage, in: adjustedRect , from: (ciSourceImage?.extent)!)
- 哦,是的。我假设您已经找到了调整 GLKView 比例因子的技术说明。它在您的 GLKView 子类中调用一行。参见 https://developer.apple.com/library/content/qa/qa1909/_index.html
您很可能需要对这种方法进行一些调整。我目前正在处理不同源 ciImages 的方向更改问题。
我花了很长时间才找到这么多所以我想分享这些发现.. 请 post 您发现的任何改进!
希望对您有所帮助 威尔L-B
使 contentMode 以与 UIView 类似的方式工作。我做了以下 class.
final class ContenModeEnforcer {
static func rectFor(contentMode: UIViewContentMode, fromRect: CGRect, toRect: CGRect) -> CGRect {
switch contentMode {
case .scaleToFill:
return toRect
case .scaleAspectFit:
return aspectFit(fromRect, toRect: toRect)
case .scaleAspectFill:
return aspectFill(fromRect, toRect: toRect)
case .redraw:
return fromRect
case .center:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .top:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .bottom:
let origin = CGPoint(
x: (toRect.size.width - fromRect.size.width) / 2,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
case .left:
let origin = CGPoint(
x: 0.0,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .right:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: (toRect.size.height - fromRect.size.height) / 2)
return CGRect(origin: origin, size: fromRect.size)
case .topLeft:
let origin = CGPoint(
x: 0.0,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .topRight:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: 0.0)
return CGRect(origin: origin, size: fromRect.size)
case .bottomLeft:
let origin = CGPoint(
x: 0.0,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
case .bottomRight:
let origin = CGPoint(
x: toRect.size.width - fromRect.size.width,
y: toRect.size.height - fromRect.size.height)
return CGRect(origin: origin, size: fromRect.size)
}
}
static fileprivate func aspectFit(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
let fromAspectRatio = fromRect.size.width / fromRect.size.height;
let toAspectRatio = toRect.size.width / toRect.size.height;
var fitRect = toRect
if (fromAspectRatio > toAspectRatio) {
fitRect.size.height = toRect.size.width / fromAspectRatio;
fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
} else {
fitRect.size.width = toRect.size.height * fromAspectRatio;
fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
}
return fitRect.integral
}
static fileprivate func aspectFill(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
let fromAspectRatio = fromRect.size.width / fromRect.size.height;
let toAspectRatio = toRect.size.width / toRect.size.height;
var fitRect = toRect
if (fromAspectRatio > toAspectRatio) {
fitRect.size.width = toRect.size.height * fromAspectRatio;
fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
} else {
fitRect.size.height = toRect.size.width / fromAspectRatio;
fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
}
return fitRect.integral
}
}
在抽奖中(_:CGRect).
let inputBounds = image.extent
let drawableBounds = CGRect(x: 0, y: 0, width: self.drawableWidth, height: self.drawableHeight)
let targetBounds = ContenModeEnforcer.rectFor(contentMode: contentMode, fromRect: inputBounds, toRect: drawableBounds)
ciContext.draw(image, in: targetBounds, from: inputBounds)