Swift 5
The code from shallowThought works, but for Swift 5 generates warnings:
Initialization of 'UnsafeMutablePointer<vImagePixelCount>'
(aka 'UnsafeMutablePointer<UInt>') results in a dangling pointer
To follow up Valerly Van's comments to shallowThought's accepted answer, here's Swift 5 code that eliminates the warnings. The code below is copied, pasted, and mashed together from two sources.
Apple's example, "Specifying Histograms with vImage"
https://developer.apple.com/documentation/accelerate/specifying_histograms_with_vimage
An SO post about generating and using histograms, Swift 2.2 - Count Black Pixels in UIImage
func histogram(image: UIImage) -> (red: [UInt], green: [UInt], blue: [UInt], alpha: [UInt]) {
let img: CGImage = CIImage(image: image)!.cgImage!
let imgProvider: CGDataProvider = img.dataProvider!
let imgBitmapData: CFData = imgProvider.data!
var imgBuffer = vImage_Buffer(
data: UnsafeMutableRawPointer(mutating: CFDataGetBytePtr(imgBitmapData)),
height: vImagePixelCount(img.height),
width: vImagePixelCount(img.width),
rowBytes: img.bytesPerRow)
// bins: zero = red, green = one, blue = two, alpha = three
var binZero = [vImagePixelCount](repeating: 0, count: 256)
var binOne = [vImagePixelCount](repeating: 0, count: 256)
var binTwo = [vImagePixelCount](repeating: 0, count: 256)
var binThree = [vImagePixelCount](repeating: 0, count: 256)
binZero.withUnsafeMutableBufferPointer { zeroPtr in
binOne.withUnsafeMutableBufferPointer { onePtr in
binTwo.withUnsafeMutableBufferPointer { twoPtr in
binThree.withUnsafeMutableBufferPointer { threePtr in
var histogramBins = [zeroPtr.baseAddress, onePtr.baseAddress,
twoPtr.baseAddress, threePtr.baseAddress]
histogramBins.withUnsafeMutableBufferPointer {
histogramBinsPtr in
let error = vImageHistogramCalculation_ARGB8888(
&imgBuffer,
histogramBinsPtr.baseAddress!,
vImage_Flags(kvImageNoFlags))
guard error == kvImageNoError else {
fatalError("Error calculating histogram: \(error)")
}
}
}
}
}
}
return (binZero, binOne, binTwo, binThree)
}
Matching up the bins (zero, one, two, three) with (red, green, blue, alpha) happens to work for my current and rather limited use case.