我目前正在实现某种着色书,我很好奇更改 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
}
问题是,每次我更改像素时,我都必须在 context
上调用 makeImage
来生成新图像,这会花费很多时间:
func generateImage() -> UIImage {
let cgImage = context.makeImage()!
let uiimage = UIImage(cgImage: cgImage)
return uiimage
}
我的做法是否正确?有什么更好更快的实现方法?谢谢。
最佳答案
操作单个像素,然后将整个内存缓冲区复制到 CGContext,然后使用该上下文创建 UIImage 最终会变得效率低下,正如您所发现的。
您可以通过更有效地将屏幕外的部分复制到屏幕上来继续改进和优化 CoreGraphics Canvas 方法。您可以检测已更改的像素,并仅将这些像素的最小边界矩形复制到屏幕上。对于您仅用颜色填充区域的用例,这种方法可能足够好。
与其复制整个屏幕外,不如复制更改的区域:
self.context?.draw(image.cgImage, in: CGRect(x: diffX, y: diffY, width: diffWidth, height: diffHeight))
由您决定更改的矩形以及何时更新屏幕。
Here是一个使用 CoreGraphics、CoreImage 和 CADisplayLink 的绘画应用程序示例。代码有点旧,但概念仍然有效,可以作为一个很好的起点。您可以使用 CADisplayLink 查看更改是如何累积并绘制到屏幕上的。
如果您想引入各种类型的墨水和绘画效果,CoreGraphics 方法将更具挑战性。您将需要查看 Apple 的 Metal API。一个很好的教程是here .
关于ios - 在 iOS 中更改像素的最佳方法,swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58573194/