CIImage 在应用于 CIFilter 时会调整大小

CIImage gets resized when applying to CIFilter

我正在尝试为我的视频添加全屏水印。

不幸的是,CIFilter 调整了水印图像(红色矩形)的大小,我找不到让它全屏显示的方法。

有没有办法设置 CIImage 的大小?

 let watermarkFilter = CIFilter(name: "CISourceOverCompositing")!
 let watermarkImage = CIImage(image: image)


 let videoComposition = AVVideoComposition(asset: asset) { (filteringRequest) in


    let source = filteringRequest.sourceImage.clampedToExtent()

    watermarkFilter.setValue(source, forKey: "inputBackgroundImage")

    watermarkFilter.setValue(watermarkImage, forKey: "inputImage")
    let output = watermarkFilter.outputImage!

    filteringRequest.finish(with: output, context: nil)

}

我也试过放大 CIImage,但这也不起作用。

func addImageToVideo(inputURL: URL, image: UIImage,  handler: @escaping (_ exportSession: AVAssetExportSession?)-> Void) {

        let mixComposition = AVMutableComposition()
        let asset = AVAsset(url: inputURL)
        let videoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]
        let timerange = CMTimeRangeMake(kCMTimeZero, asset.duration)

        let compositionVideoTrack:AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))!

        do {
            try compositionVideoTrack.insertTimeRange(timerange, of: videoTrack, at: kCMTimeZero)
            compositionVideoTrack.preferredTransform = videoTrack.preferredTransform
        } catch {
            print(error)
        }

        let watermarkFilter = CIFilter(name: "CISourceOverCompositing")!
        let watermarkImage = CIImage(image: image)


        //Filer method
        let videoComposition = AVVideoComposition(asset: asset) { (filteringRequest) in

            let sourceImage = filteringRequest.sourceImage.clampedToExtent()

            var transform = CGAffineTransform.identity
            let scaleX = image.size.width / image.scale
            let scaleY = image.size.height / image.scale

            transform = transform.scaledBy(x: scaleX, y: scaleY)
            let transformFilter = CIFilter(name: "CIAffineClamp")!
            transformFilter.setValue( watermarkImage, forKey: "inputImage" )
            transformFilter.setValue( transform, forKey: "inputTransform")

            watermarkFilter.setValue(sourceImage, forKey: "inputBackgroundImage")
            watermarkFilter.setValue(transformFilter.outputImage, forKey: "inputImage")
            let output = watermarkFilter.outputImage!

            filteringRequest.finish(with: output, context: nil)

        }

        guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
            handler(nil)
            return
        }

        exportSession.outputURL = outputURL
        exportSession.outputFileType = AVFileType.mp4
        exportSession.shouldOptimizeForNetworkUse = true
        exportSession.videoComposition = videoComposition
        exportSession.exportAsynchronously { () -> Void in
            handler(exportSession)
        }
    }

我真的不知道该怎么做,我已经花了几个星期试图简单地将水印渲染到视频中,但不幸的是,这根本行不通。

我用来调整 CIImage 大小的一种方法是使用 CIAffineClamp 过滤器,这是我使用的示例:

var transform = CGAffineTransform.identity
let scaleX = sourceImage.extent.width / watermarkImage.extent.width
let scaleY = sourceImage.extent.height / watermarkImage.extent.height
transform = transform.scaledBy(x: scaleX, y: scaleY)

let transformFilter = CIFilter(name: "CIAffineClamp", withInputParameters: [:]) {
    transformFilter.setValue(watermarkImage, forKey: kCIInputImageKey)
    transformFilter.setValue(NSValue(cgAffineTransform: transform), forKey: "inputTransform")
}

然后使用您的 CISourceOverCompositing 过滤器,仅对于 inputImage 使用 transformFilter.outputImage 而不是 watermarkImage

只需使用比例参数,您就会得到结果。 如果你会得到意想不到的结果,这意味着你的源图像被旋转了,所以添加以下参数来修复它:

transform = transform.translatedBy(x: watermarkImage.extent.midY, y: watermarkImage.extent.midX)
transform = transform.rotated(by: CGFloat(degrees * Double.pi / 180))
transform = transform.translatedBy(x: -watermarkImage.extent.midX, y: -watermarkImage.extent.midY)
transform = transform.translatedBy(x: 0.0, y: -watermarkImage.extent.x / scaleX)

如果你使用iPad,相机输出也可能不同,所以你的比例参数也应该不同,像这样:

if idiom == .pad {
     scaleX = sourceImage.extent.height / watermarkImage.extent.height
     scaleY = sourceImage.extent.width / watermarkImage.extent.width
} else {
     scaleX = sourceImage.extent.height / watermarkImage.extent.width
     scaleY = sourceImage.extent.width / watermarkImage.extent.height
}

前置摄像头的摄像头设置与后置摄像头的设置不同,iPad 的设置与 iPhone 的设置不同,因此请彻底测试所有内容并相应地应用转换。