我正在制作一个OS X应用程序,该应用程序从图像的主要颜色创建配色方案。
第一步,我使用NSCountedSet
和colorAtX
从图像中获取所有颜色并计算它们的出现:
func sampleImage(#width: Int, height: Int, imageRep: NSBitmapImageRep) -> (NSCountedSet, NSCountedSet) {
// Store all colors from image
var colors = NSCountedSet(capacity: width * height)
// Store the colors from left edge of the image
var leftEdgeColors = NSCountedSet(capacity: height)
// Loop over the image pixels
var x = 0
var y = 0
while x < width {
while y < height {
// Instruments shows that `colorAtX` is very slow
// and using `NSCountedSet` is also very slow
if let color = imageRep.colorAtX(x, y: y) {
if x == 0 {
leftEdgeColors.addObject(color)
}
colors.addObject(color)
}
y++
}
// Reset y every x loop
y = 0
// We sample a vertical line every x pixels
x += 1
}
return (colors, leftEdgeColors)
}
我的问题是,这非常慢。在Instruments中,我看到了两个大瓶颈:
NSCountedSet
和colorAtX
。所以首先我想也许可以用一个纯Swift替代物替换
NSCountedSet
,但是新的实现并不比NSCountedSet
慢得多。对于
colorAtX
,有一个this有趣的SO答案,但我无法将其转换为Swift(并且对于该项目,我无法在Objective-C中使用桥接头)。我在尝试翻译时的问题是我不理解答案中的
unsigned char
和char
部分。我应该尝试比
colorAtX
更快地扫描颜色吗?继续努力修改Objective-C答案,因为这是一个很好的答案?尽管暂时停滞不前,也许我以后可以实现。
使用我不知道的另一种Foundation / Cocoa方法?
还有什么我可以尝试改进我的代码的吗?
TL; DR
colorAtX
很慢,由于unsigned char
我不知道如何将this Objective-C answer适应Swift。 最佳答案
替代colorAtX()最快的方法是使用let bitmapBytes = imageRep.bitmapData
遍历图像的原始字节,然后根据该信息自行组成颜色,如果只是RGBA数据,这应该非常简单。代替您的for x / y循环,执行以下操作...
let bitmapBytes = imageRep.bitmapData
var colors = Dictionary<UInt32, Int>()
var index = 0
for _ in 0..<(width * height) {
let r = UInt32(bitmapBytes[index++])
let g = UInt32(bitmapBytes[index++])
let b = UInt32(bitmapBytes[index++])
let a = UInt32(bitmapBytes[index++])
let finalColor = (r << 24) + (g << 16) + (b << 8) + a
if colors[finalColor] == nil {
colors[finalColor] = 1
} else {
colors[finalColor]!++
}
}
我猜想,您将不得不检查RGBA值的顺序!
保持计数最快的方法可能只是将像素值转换为[Int,Int]字典,进行类似
colors[color]++
的操作。稍后,如果需要,您可以使用NSColor(calibratedRed red: CGFloat, green green: CGFloat, blue blue: CGFloat, alpha alpha: CGFloat)
将其转换为NSColor。关于objective-c - 计算图像中的颜色:NSCountedSet和colorAtX非常慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31026763/