2016-05-05 39 views
0

鉴于CGRect,我想使用GPUImage裁剪视频。例如,如果矩形是(0, 0, 50, 50),则视频将在(0,0)处裁剪,每边长度为50。GPUImage裁剪到CGRect并旋转

什么扔我是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() 
     } 

回答

3

当你注意,GPUImageCropFilter需要在标准化坐标的矩形。您正处在正确的轨道上,因为您只需将CGRect以像素为单位转换为标准化坐标,方法是将X分量(origin.x和size.width)除以图像宽度,Y分量除以高度。

您不需要使用forceProcessingAtSize(),因为裁剪会自动输出适当裁剪尺寸的图像。电影作者的尺寸应该与这个裁剪尺寸相匹配,你应该从原始CGRect中知道。

你介绍的一个复杂因素是旋转。如果除了裁剪之外还需要应用旋转,则可能需要检查并确保不需要将裁剪区域的X和Y交换。如果两者需要交换,这应该在输出中显而易见。

前段时间有一些与作物同时施加旋转的错误,我不记得我是否修复了所有这些错误。如果我没有,可以在裁剪之前或之后插入虚拟滤镜(伽玛或亮度设置为默认值),并在该阶段应用旋转。

+0

是的,我认为你是对的,因为如果我将'videoTrack.preferredTransform'应用到我的裁剪区域,然后剪裁和输出,输出的视频就会旋转,但是会根据我的需要进行裁剪。然后,如果我通过一个旋转过滤器运行它,旋转工作,但我在视频的一侧没有,也不应该在那里得到黑条。 – barndog

+0

我发布了我终于开始工作的代码。事实证明,我根本不必使用旋转滤镜,我只是将电影编写器的变换设置为视频轨道的变换。 虽然有两件事,你可能知道一些事情。当我导出一部电影并通过xcode打开我的文档文件夹时,会发生两件事:1)我裁剪的所有电影都有黑条。 2)当我点击播放电影时,quicktime转换文件并转换摆脱侧边栏。任何想法是什么? – barndog