iOS中的大型图像合成Swift

时间:2016-03-13 11:27:43

标签: ios iphone swift image

虽然我理解图像合成背后的理论,但我还没有解决硬件加速问题,而且我在iOS(9.2,iPhone 6S)上遇到了实施问题。我的项目是按顺序将大量图像(20个,一直到数百个)的大图像(12百万像素)依次组合在一起,同时减少不透明度,我正在寻找有关最佳框架或技术的建议。我知道必须有一个好的,硬件加速的,破坏性的合成工具,能够处理iOS上的大文件,因为我可以在Safari中以HTML Canvas标签执行此任务,并在iPhone上的Safari中加载此页面几乎相同的炽热速度。

这可能是一个破坏性的合成任务,就像在Canvas中绘画一样,所以我不应该有内存问题,因为手机只需将当前结果存储到那一点。理想情况下,我喜欢浮点像素组件,我也希望能够在屏幕上看到进度。

Core Image具有看起来很棒的过滤器,但它们旨在无损地在一张或两张图片上运行并返回一个结果。我可以使用下一个图像将该结果再次输入到过滤器中,依此类推,但由于过滤器不会立即渲染,因此在大约60张图像后,这种过滤器链接会使我失去内存。渲染到Core Graphics图像对象并在每个过滤器之后作为Core Image对象读回也没有帮助,因为这会使内存过载更快。

查看文档,iOS有许多其他方式可以利用GPU - CALayers就是一个很好的例子。但是我不清楚它是否处理大于屏幕的图片,或者仅用于屏幕大小的帧缓冲区。

完成此任务 - 利用GPU存储破坏性合成的堆栈" 12百万像素的照片,并在指定的不透明度上重复添加一个额外的一个,同时输出缩小到屏幕的堆栈的当前内容 - 最好的方法是什么?我可以使用既定的框架/技术,还是我最好自己深入了解OpenGL和Metal?我知道iPhone具有这种功能,我只需要弄清楚如何利用它。

这是我到目前为止所得到的。 Profiler告诉我渲染需要大约350毫秒,但如果我增加到20个图片我会耗尽内存。如果我在每次循环后都没有渲染,那么在运行内存之前,我可以增加到大约60张照片。

var stackBuffer: CIImage!
var stackRender: CGImage!
var uiImage: UIImage!

let glContext = EAGLContext(API: .OpenGLES3)
let context = CIContext(EAGLContext: glContext)

// Preload list of 10 test pics
var ciImageArray = Array(count: 10, repeatedValue: CIImage.emptyImage())
for i in 0...9 {
    uiImage = UIImage(named: String(i) + ".jpg")!
    ciImageArray[i] = CIImage(image: uiImage)!
}

// Put the first image in the buffer
stackBuffer = ciImageArray[0]
for i in 1...9 {

    // The next image will have an opacity of 1/n
    let topImage = ciImageArray[i]
    let alphaTop = topImage.imageByApplyingFilter(
        "CIColorMatrix", withInputParameters: [
        "inputAVector"  : CIVector(x:0, y:0, z:0, w:1/CGFloat(i + 1))
        ])

    // Layer the next image on top of the stack
    let filter = CIFilter(name: "CISourceOverCompositing")!
    filter.setValue(alphaTop, forKey: kCIInputImageKey)
    filter.setValue(stackBuffer, forKey: kCIInputBackgroundImageKey)

    // Render the result, and read back in
    stackRender = context.createCGImage(filter.outputImage!, fromRect: stackBuffer.extent)
    stackBuffer = CIImage(CGImage: stackRender)
}

// Output result
uiImage = UIImage(CGImage: stackRender)
compositeView.image = uiImage

0 个答案:

没有答案