Created
March 15, 2017 15:28
-
-
Save adamcichy/2d00c7a54009b4a9751ba513749c485e to your computer and use it in GitHub Desktop.
Determine if a UIImage is generally dark or generally light in Swift 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extension CGImage { | |
| var isDark: Bool { | |
| get { | |
| guard let imageData = self.dataProvider?.data else { return false } | |
| guard let ptr = CFDataGetBytePtr(imageData) else { return false } | |
| let length = CFDataGetLength(imageData) | |
| let threshold = Int(Double(self.width * self.height) * 0.45) | |
| var darkPixels = 0 | |
| for i in stride(from: 0, to: length, by: 4) { | |
| let r = ptr[i] | |
| let g = ptr[i + 1] | |
| let b = ptr[i + 2] | |
| let luminance = (0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b)) | |
| if luminance < 150 { | |
| darkPixels += 1 | |
| if darkPixels > threshold { | |
| return true | |
| } | |
| } | |
| } | |
| return false | |
| } | |
| } | |
| } | |
| extension UIImage { | |
| var isDark: Bool { | |
| get { | |
| return self.cgImage?.isDark ?? false | |
| } | |
| } | |
| } |
@toniocrq this code is slightly incorrect, you are reading the same pixel every time in the for loop.
Here is my fix
`
let pixels = self.width*self.height
let bytesPerPixel = self.bitsPerPixel / self.bitsPerComponent
var result: Double = 0
for y in 0..<self.height {
for x in 0..<self.width {
let offset = (y * self.bytesPerRow) + (x * bytesPerPixel)
let r = ptr![offset]
let g = ptr![offset + 1]
let b = ptr![offset + 2]
`
Taking into account all versions above:
func getBrightness(for image: UIImage) -> Int? {
guard let cgImage = image.cgImage,
let imageData = cgImage.dataProvider?.data,
let dataPointer = CFDataGetBytePtr(imageData) else {
return nil
}
let bytesPerPixel = cgImage.bitsPerPixel / cgImage.bitsPerComponent
let dataLength = CFDataGetLength(imageData)
var result = 0.0
for i in stride(from: 0, to: dataLength, by: bytesPerPixel) {
let r = dataPointer[i]
let g = dataPointer[i + 1]
let b = dataPointer[i + 2]
result += 0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b)
}
let pixelsCount = dataLength / bytesPerPixel
let brightness = Int(result) / pixelsCount
return brightness
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nevermind I reread it and it's fine, just jumping the gun thinking I had figured something out.