iosswiftuicolorcgimage

How to replace the color of a pixel in an image?


I have a function that can return the color of a pixel by points

extension CGImage {
func colors(at: CGPoint) -> UIColor {
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * width
    let bitsPerComponent = 8
    let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

    guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
        let ptr = context.data?.assumingMemoryBound(to: UInt8.self) else {
            return .black
    }

    context.draw(self, in: CGRect(x: 0, y: 0, width: width, height: height))
    let i = bytesPerRow * Int(at.y) + bytesPerPixel * Int(at.x)
    
    let a = CGFloat(ptr[i + 3]) / 255.0
    let r = (CGFloat(ptr[i]) / a) / 255.0
    let g = (CGFloat(ptr[i + 1]) / a) / 255.0
    let b = (CGFloat(ptr[i + 2]) / a) / 255.0
    
        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}

I would like to write a function that could replace the color of a pixel by Point Can you please advise where to start?


Solution

  • Depending on what all you want to do, this may or may not be the appropriate approach.

    However, without additional information...

    This func will set the pixel at atPoint to on onImage to color:

    func setColor(color: UIColor, onImage: UIImage, atPoint: CGPoint) -> UIImage {
        let rndr = UIGraphicsImageRenderer(size: onImage.size)
        let newImg = rndr.image { ctx in
            onImage.draw(at: .zero)
            let r = CGRect(origin: atPoint, size: CGSize(width: 1, height: 1))
            ctx.cgContext.setFillColor(color.cgColor)
            ctx.cgContext.addRect(r)
            ctx.cgContext.drawPath(using: .fill)
        }
        return newImg
    }
    

    You can call it like this:

        guard let image = UIImage(named: "pixelTest") else { return }
    
        let modifiedImage = setColor(color: .red, onImage: image, atPoint: CGPoint(x: 5, y: 5))