Ios GPUImage裁剪到CGRect并旋转
给定一个Ios GPUImage裁剪到CGRect并旋转,ios,swift,gpuimage,Ios,Swift,Gpuimage,给定一个CGRect,我想使用GPUImage来裁剪视频。例如,如果rect是(0,0,50,50),则视频将在(0,0)处剪切,每侧的长度为50 让我感到困惑的是,GPUImageCropFilter不采用矩形,而是采用值范围为0到1的标准化裁剪区域。我的直觉是: let assetSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform) let cropRect = CGR
CGRect
,我想使用GPUImage来裁剪视频。例如,如果rect是(0,0,50,50)
,则视频将在(0,0)
处剪切,每侧的长度为50
让我感到困惑的是,GPUImageCropFilter
不采用矩形,而是采用值范围为0到1的标准化裁剪区域。我的直觉是:
let assetSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform)
let cropRect = CGRect(x: frame.minX/assetSize.width,
y: frame.minY/assetSize.height,
width: frame.width/assetSize.width,
height: frame.height/assetSize.height)
根据传入资源的大小计算裁剪区域。然后:
// Filter
let cropFilter = GPUImageCropFilter(cropRegion: cropRect)
let url = NSURL(fileURLWithPath: "\(NSTemporaryDirectory())\(String.random()).mp4")
let movieWriter = GPUImageMovieWriter(movieURL: url, size: assetSize)
movieWriter.encodingLiveVideo = false
movieWriter.shouldPassthroughAudio = false
// add targets
movieFile.addTarget(cropFilter)
cropFilter.addTarget(movieWriter)
cropFilter.forceProcessingAtSize(frame.size)
cropFilter.setInputRotation(kGPUImageRotateRight, atIndex: 0)
电影编剧的尺寸应该是多少?它不应该是我想要裁剪的框架的大小吗?我是否应该对裁剪框的大小值使用forceProcessingAtSize
一个完整的代码示例会很好;我已经试了几个小时了,但我似乎无法得到我想要的视频部分
最终:
if let videoTrack = self.asset.tracks.first {
let movieFile = GPUImageMovie(asset: self.asset)
let transformedRegion = CGRectApplyAffineTransform(region, videoTrack.preferredTransform)
// Filters
let cropFilter = GPUImageCropFilter(cropRegion: transformedRegion)
let url = NSURL(fileURLWithPath: "\(NSTemporaryDirectory())\(String.random()).mp4")
let renderSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, CGAffineTransformMakeScale(transformedRegion.width, transformedRegion.height))
let movieWriter = GPUImageMovieWriter(movieURL: url, size: renderSize)
movieWriter.transform = videoTrack.preferredTransform
movieWriter.encodingLiveVideo = false
movieWriter.shouldPassthroughAudio = false
// add targets
// http://stackoverflow.com/questions/37041231/gpuimage-crop-to-cgrect-and-rotate
movieFile.addTarget(cropFilter)
cropFilter.addTarget(movieWriter)
movieWriter.completionBlock = {
observer.sendNext(url)
observer.sendCompleted()
}
movieWriter.failureBlock = { _ in
observer.sendFailed(.VideoCropFailed)
}
disposable.addDisposable {
cropFilter.removeTarget(movieWriter)
movieWriter.finishRecording()
}
movieWriter.startRecording()
movieFile.startProcessing()
}
正如您所注意到的,GPUImageCropFilter在标准化坐标中采用矩形。这是正确的,只需将X分量(origin.X和size.width)除以图像的宽度,将Y分量除以高度,即可将以像素为单位的CGRect转换为标准化坐标 您不需要使用
forceProcessingAtSize()
,因为裁剪将自动输出适当裁剪大小的图像。电影编剧的大小应该与这个裁剪的大小相匹配,您应该从原始CGRect中了解到这一点
你引入的一个复杂因素是旋转。如果需要在裁剪之外应用旋转,则可能需要检查并确保不需要为裁剪区域交换X和Y。如果两者需要交换,则这一点在输出中应该很明显
前一段时间,在作物生长的同时应用轮作时出现了一些错误,我不记得是否修复了所有这些错误。如果我没有这样做,您可以在裁剪之前或之后插入一个虚拟过滤器(gamma或亮度设置为默认值),并在该阶段应用旋转。正如您所注意的,GPUImageCropFilter在标准化坐标中采用矩形。这是正确的,只需将X分量(origin.X和size.width)除以图像的宽度,将Y分量除以高度,即可将以像素为单位的CGRect转换为标准化坐标 您不需要使用
forceProcessingAtSize()
,因为裁剪将自动输出适当裁剪大小的图像。电影编剧的大小应该与这个裁剪的大小相匹配,您应该从原始CGRect中了解到这一点
你引入的一个复杂因素是旋转。如果需要在裁剪之外应用旋转,则可能需要检查并确保不需要为裁剪区域交换X和Y。如果两者需要交换,则这一点在输出中应该很明显
前一段时间,在作物生长的同时应用轮作时出现了一些错误,我不记得是否修复了所有这些错误。如果我没有这样做,您可以在裁剪之前或之后插入一个虚拟过滤器(gamma或亮度设置为默认值),并在该阶段应用旋转。是的,我认为您是对的,因为如果我应用
videoTrack.preferredTransform
到裁剪区域,然后进行裁剪和输出,输出的视频是旋转的,但按我所希望的方式进行裁剪。然后,如果我通过一个旋转过滤器运行它,旋转是有效的,但我会在视频的一侧看到黑色的条带,这些条带不存在,也不应该存在。我发布了我最终能够工作的代码。事实证明,我根本不需要使用旋转过滤器,我只是将电影编写器的变换设置为视频轨迹的变换。不过,有两件事你可能知道一些。当我导出一部电影并通过xcode打开我的文档文件夹时,会发生两件事:1)我剪切的所有电影的旁边都有一个黑条。2) 当我单击播放电影时,quicktime会转换文件,并且转换过程中会去掉边栏。知道这是怎么回事吗?是的,我想你是对的,因为如果我应用videoTrack.preferredTransform
到我的裁剪区域,然后裁剪和输出,输出的视频会旋转,但裁剪的方式正是我想要的。然后,如果我通过一个旋转过滤器运行它,旋转是有效的,但我会在视频的一侧看到黑色的条带,这些条带不存在,也不应该存在。我发布了我最终能够工作的代码。事实证明,我根本不需要使用旋转过滤器,我只是将电影编写器的变换设置为视频轨迹的变换。不过,有两件事你可能知道一些。当我导出一部电影并通过xcode打开我的文档文件夹时,会发生两件事:1)我剪切的所有电影的旁边都有一个黑条。2) 当我单击播放电影时,quicktime会转换文件,并且转换过程中会去掉边栏。知道那是怎么回事吗?