首页 > 解决方案 > 在 iOS 中快速更改像素的最佳方法

问题描述

我目前正在实施某种着色书,我很好奇在UIImage. 这是我的代码:

self.context = CGContext(data: nil, width: image.width, height: image.height, bitsPerComponent: 8, bytesPerRow: image.width * 4, space: colorSpace, bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)!
self.context?.draw(image.cgImage, in: CGRect(x: 0, y: 0, width: CGFloat(image.width), height: CGFloat(image.height)))
let ptr = context.data
self.pixelBuffer = ptr!.bindMemory(to: UInt32.self, capacity: image.width * image.height)

并使用此功能更改像素:

@inline (__always) func fill(matrixPosition: MatrixPosition, color: UInt32) {
    pixelsBuffer?[self.linearIndex(for: matrixPosition)] = color
}

问题是每次我更改像素时,我都必须调用makeImagecontext来生成新图像,这需要很长时间:

func generateImage() -> UIImage {
    let cgImage = context.makeImage()!
    let uiimage = UIImage(cgImage: cgImage)

    return uiimage
}

我的方法正确吗?有什么更好更快的方法来实现它?谢谢。

标签: iosswiftcore-graphics

解决方案


正如您所发现的,操作单个像素,然后将整个内存缓冲区复制到 CGContext,然后使用该上下文创建 UIImage 最终会效率低下。

您可以通过更有效地将屏幕外的哪些部分复制到屏幕上来继续改进和优化 CoreGraphics 画布方法。您可以检测已更改的像素,并仅将这些像素的最小边界矩形复制到屏幕上。对于您只用颜色填充区域的用例,这种方法可能已经足够了。

不要复制整个屏幕外,只复制更改的区域:

self.context?.draw(image.cgImage, in: CGRect(x: diffX, y: diffY, width: diffWidth, height: diffHeight))

由您决定更改的矩形以及何时更新屏幕。

是一个使用 CoreGraphics、CoreImage 和 CADisplayLink 的绘画应用程序示例。代码有点旧,但概念仍然有效,可以作为一个很好的起点。您可以使用 CADisplayLink 查看更改是如何累积并绘制到屏幕上的。

如果您想引入各种类型的墨水和绘画效果,CoreGraphics 方法将更具挑战性。您将需要查看 Apple 的 Metal API。一个很好的教程在这里


推荐阅读