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 | |
| } | |
| } | |
| } |
Any idea on which method works best?
@toniocrq do you have links/resources or can you also share the algorithm that worked for you? thank you in advanced.
I calculated the brightness.
If the brightness is between 34 and 227 the image is good for me.
extension CGImage {
var brightness: Double {
get {
let imageData = self.dataProvider?.data
let ptr = CFDataGetBytePtr(imageData)
var x = 0
var result: Double = 0
for _ in 0..<self.height {
for _ in 0..<self.width {
let r = ptr![0]
let g = ptr![1]
let b = ptr![2]
result += (0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b))
x += 1
}
}
let bright = result / Double (x)
return bright
}
}
}
extension UIImage {
var brightness: Double {
get {
return (self.cgImage?.brightness)!
}
}
}
Hi @toniocrq thank you for this! though what does 34-227 mean?
@alvincrisuy It's a range that i use for the returned bright.
It goes from 0 to 255.
If the image's brightness is < 34 , the image is too dark, if is > 227 is too bright.
Nevermind I reread it and it's fine, just jumping the gun thinking I had figured something out.
@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
Hi @alvincrisuy, no i didn't. I found another algorithm and it worked. Thank you by the way.