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 | |
} | |
} | |
} |
Hi, I'm trying this solution on my set of UIImages but it returns me always a true value on very bright images, I also resized the image but doesn't work anyway. Do you have any idea why your solution couldn't work. Thanks
//Resize Function
func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
It seems like yes it is always returning true. @toniocrq have you solved this?
Hi @alvincrisuy, no i didn't. I found another algorithm and it worked. Thank you by the way.
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]
`
This is a Swift version of this Objective-C method: https://gist.github.com/justinHowlett/4611988