【问题标题】:GPUImage crop to CGRect and rotateGPUImage 裁剪为 CGRect 并旋转
【发布时间】:2016-05-05 02:17:00
【问题描述】:

给定CGRect,我想使用 GPUImage 裁剪视频。例如,如果矩形是(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()
        }

【问题讨论】:

    标签: ios swift gpuimage


    【解决方案1】:

    正如您所注意到的,GPUImageCropFilter 采用标准化坐标中的矩形。您在正确的轨道上,因为您只需要通过将 X 分量(origin.x 和 size.width)除以图像的宽度和 Y 分量除以高度来将像素中的 CGRect 转换为标准化坐标。

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

    您引入的一种复杂情况是旋转。如果除了裁剪之外还需要应用旋转,您可能需要检查并确保不需要为裁剪区域交换 X 和 Y。如果需要交换两者,这在输出中应该很明显。

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

    【讨论】:

    • 是的,我认为你是对的,因为如果我将videoTrack.preferredTransform 应用到我的裁剪区域,然后裁剪和输出,输出的视频会旋转,但会按照我想要的方式裁剪。然后,如果我通过旋转过滤器运行它,旋转会起作用,但我会在视频的一侧看到不存在也不应该存在的黑条。
    • 我发布了我终于开始工作的代码。结果我根本不需要使用旋转过滤器,我只是将电影作者的变换设置为视频轨道的变换。不过有两件事,你可能知道一些事情。当我通过 xcode 导出电影并打开我的文档文件夹时,会发生两件事:1)我裁剪的所有电影的侧面都有一个黑条。 2)当我点击播放电影时,quicktime转换文件并且转换摆脱了侧边栏。知道那是什么意思吗?
    猜你喜欢
    • 2020-12-25
    • 2013-04-21
    • 2021-11-18
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 2013-08-21
    • 2013-10-21
    相关资源
    最近更新 更多