有没有办法提高每像素绘制像素到UIView的速度/性能?
500x500像素UIView的当前实现非常慢。
class CustomView: UIView {
public var context = UIGraphicsGetCurrentContext()
public var redvalues = [[CGFloat]](repeating: [CGFloat](repeating: 1.0, count: 500), count: 500)
public var start = 0
{
didSet{
self.setNeedsDisplay()
}
}
override func draw(_ rect: CGRect
{
super.draw(rect)
context = UIGraphicsGetCurrentContext()
for yindex in 0...499{
for xindex in 0...499 {
context?.setStrokeColor(UIColor(red: redvalues[xindex][yindex], green: 0.0, blue: 0.0, alpha: 1.0).cgColor)
context?.setLineWidth(2)
context?.beginPath()
context?.move(to: CGPoint(x: CGFloat(xindex), y: CGFloat(yindex)))
context?.addLine(to: CGPoint(x: CGFloat(xindex)+1.0, y: CGFloat(yindex)))
context?.strokePath()
}
}
}
}
非常感谢
答案 0 :(得分:1)
绘制单个像素时,可以使用a bitmap context.位图上下文将原始像素数据作为输入。
上下文会复制您的原始像素数据,因此您不必使用可能要慢得多的路径。然后,您可以使用CGImage
获得context.makeImage()
。
然后可以在图像视图中使用图像,这样就无需每帧重绘整个图像。
如果您不想手动创建位图上下文,可以使用
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()
// draw everything into the context
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
然后您可以使用UIImageView
来显示渲染图像。
也可以绘制成CALayer
,不需要每帧重绘,但只有在调整大小时才会重绘。
答案 1 :(得分:0)
现在的样子,是否有可能进行优化?
public struct rgba {
var r:UInt8
var g:UInt8
var b:UInt8
var a:UInt8
}
public let imageview = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
let width_input = 500
let height_input = 500
let redPixel = rgba(r:255, g:0, b:0, a:255)
let greenPixel = rgba(r:0, g:255, b:0, a:255)
let bluePixel = rgba(r:0, g:0, b:255, a:255
var pixelData = [rgba](repeating: redPixel, count: Int(width_input*height_input))
pixelData[1] = greenPixel
pixelData[3] = bluePixel
self.view.addSubview(imageview)
imageview.frame = CGRect(x: 100,y: 100,width: 600,height: 600)
imageview.image = draw(pixel: pixelData,width: width_input,height: height_input)
}
func draw(pixel:[rgba],width:Int,height:Int) -> UIImage
{
let colorSpace = CGColorSpaceCreateDeviceRGB()
let data = UnsafeMutableRawPointer(mutating: pixel)
let bitmapContext = CGContext(data: data,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: 4*width,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
let image = bitmapContext?.makeImage()
return UIImage(cgImage: image!)
}
答案 2 :(得分:0)
我从Manuel那里得到了答案,并使其在Swift 5中运行。这里的主要症结在于清除Xcode 12中悬空的指针警告。
var image:CGImage?
pixelData.withUnsafeMutableBytes( { (rawBufferPtr: UnsafeMutableRawBufferPointer) in
if let rawPtr = rawBufferPtr.baseAddress {
let bitmapContext = CGContext(data: rawPtr,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: 4*width,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
image = bitmapContext?.makeImage()
}
})
我确实不得不放弃使用rgba struct方法来预先加载数据,并转移到直接从枚举中的rawValues派生的UInt32值。用于更新现有阵列的“ append”或“ replaceInRange”方法耗时数小时(我的位图很大),最终耗尽了计算机上的交换空间。
enum Color: UInt32 { // All 4 bytes long with full opacity
case red = 4278190335 // 0xFF0000FF
case yellow = 4294902015
case orange = 4291559679
case pink = 4290825215
case violet = 4001558271
case purple = 2147516671
case green = 16711935
case blue = 65535 // 0x0000FFFF
}
通过这种方法,我能够通过以下方式快速构建具有该数据量的数据缓冲区:
func prepareColorBlock(c:Color) -> Data {
var rawData = withUnsafeBytes(of:c.rawValue) { Data($0) }
rawData.reverse() // Byte order is reveresed when defined
var dataBlock = Data()
dataBlock.reserveCapacity(100)
for _ in stride(from: 0, to: 100, by: 1) {
dataBlock.append(rawData)
}
return dataBlock
}
这样,我将每个这些块附加到了可变数据实例'pixelData'中,我们就退出了。您可以调整数据的组装方式,因为我只是想在UIImageView中生成一些颜色条以验证工作。对于800x600的视图,生成并渲染整个内容大约需要2.3秒。
再次,要向曼努埃尔(Manuel)指点我正确的方向。