Reputation: 113
I am making an application that changes the colors on a map to highlight a country. Its like a code system where one country will have a specific color and if the condition allows it, that color will be changed to yellow and the rest will be green. Its similar to a tagging system to highlight specific countries based on the users input. I have seen a post on this before and i modified it so it could use parameters as the detection color. https://codedump.io/share/gEsdbwFbGT3T/1/change-color-of-certain-pixels-in-a-uiimage
here is the modified code:
func processPixelsInImage(inputImage: UIImage, r: UInt8, b: UInt8, g: UInt8) -> UIImage {
let inputCGImage = inputImage.CGImage
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = CGImageGetWidth(inputCGImage)
let height = CGImageGetHeight(inputCGImage)
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = CGImageAlphaInfo.PremultipliedFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue
let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo)!
CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), inputCGImage)
let pixelBuffer = UnsafeMutablePointer<UInt32>(CGBitmapContextGetData(context))
var currentPixel = pixelBuffer
for _ in 0 ..< Int(height) {
for _ in 0 ..< Int(width) {
let pixel = currentPixel.memory
if red(pixel) == r && green(pixel) == g && blue(pixel) == b {
currentPixel.memory = rgba(red: 0, green: 170, blue: 0, alpha: 255)
}
currentPixel = currentPixel.successor()
}
}
let outputCGImage = CGBitmapContextCreateImage(context)
let outputImage = UIImage(CGImage: outputCGImage!, scale: inputImage.scale, orientation: inputImage.imageOrientation)
return outputImage
}
func alpha(color: UInt32) -> UInt8 {
return UInt8((color >> 24) & 255)
}
func red(color: UInt32) -> UInt8 {
return UInt8((color >> 16) & 255)
}
func green(color: UInt32) -> UInt8 {
return UInt8((color >> 8) & 255)
}
func blue(color: UInt32) -> UInt8 {
return UInt8((color >> 0) & 255)
}
func rgba(red red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -> UInt32 {
return (UInt32(alpha) << 24) | (UInt32(red) << 16) | (UInt32(green) << 8) | (UInt32(blue) << 0)
}
When I use RGB values other than the color black(0,0,0) it doesnt detect and change the color. Im not sure if it is a different scaling compared to Normal CG Colors for rgb values because of the different data types but i'm still unsure of how to fully use this function. How can I detect colors other than black using RGB values and change them to another?
Upvotes: 2
Views: 1684
Reputation: 36
I tweaked similar code to change all UIImage white pixels into clear pixels
(Swift 3)
func processPixelsInImage(_ image: UIImage) -> UIImage? {
guard let inputCGImage = image.cgImage else {
//print("unable to get cgImage")
return nil
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = inputCGImage.width
let height = inputCGImage.height
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = RGBA32.bitmapInfo
guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
//print("unable to create context")
return nil
}
context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let buffer = context.data else {
//print("unable to get context data")
return nil
}
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
let white = RGBA32(red: 255, green: 255, blue: 255, alpha: 255)
let clear = RGBA32(red: 0, green: 0, blue: 0, alpha: 0)
for row in 0 ..< Int(height) {
for column in 0 ..< Int(width) {
let offset = row * width + column
if pixelBuffer[offset] == white {
pixelBuffer[offset] = clear
}
}
}
let outputCGImage = context.makeImage()!
let outputImage = UIImage(cgImage: outputCGImage, scale: image.scale, orientation: image.imageOrientation)
return outputImage
}
struct RGBA32: Equatable {
var color: UInt32
var red: UInt8 {
return UInt8((color >> 24) & 255)
}
var green: UInt8 {
return UInt8((color >> 16) & 255)
}
var blue: UInt8 {
return UInt8((color >> 8) & 255)
}
var alpha: UInt8 {
return UInt8((color >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
color = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool {
return lhs.color == rhs.color
}
}
Upvotes: 1