Tôi vấp trong câu trả lời này để tìm cách thay thế màu bằng màu khác. Vâng, vì tôi cần cho mã Swift, tôi đã có một số thử và tôi tìm thấy một giải pháp tốt đẹp. Cảm ơn @Rob vì số answer.
extension UIImageView {
@discardableResult func replace(color: UIColor, withColor replacingColor: UIColor) -> Bool {
guard let inputCGImage = self.image?.cgImage else {
return false
}
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 false
}
context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let buffer = context.data else {
return false
}
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
let inColor = RGBA32(color: color)
let outColor = RGBA32(color: replacingColor)
for row in 0 ..< Int(height) {
for column in 0 ..< Int(width) {
let offset = row * width + column
if pixelBuffer[offset] == inColor {
pixelBuffer[offset] = outColor
}
}
}
guard let outputCGImage = context.makeImage() else {
return false
}
self.image = UIImage(cgImage: outputCGImage, scale: self.image!.scale, orientation: self.image!.imageOrientation)
return true
}
}
đâu RGBA32 struct chỉ đơn giản là:
struct RGBA32: Equatable {
private var color: UInt32
var redComponent: UInt8 {
return UInt8((self.color >> 24) & 255)
}
var greenComponent: UInt8 {
return UInt8((self.color >> 16) & 255)
}
var blueComponent: UInt8 {
return UInt8((self.color >> 8) & 255)
}
var alphaComponent: UInt8 {
return UInt8((self.color >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
self.color = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
init(color: UIColor) {
let components = color.cgColor.components ?? [0.0, 0.0, 0.0, 1.0]
let colors = components.map { UInt8($0 * 255) }
self.init(red: colors[0], green: colors[1], blue: colors[2], alpha: colors[3])
}
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool {
return lhs.color == rhs.color
}
}
Bằng cách này, bất cứ nơi nào trong mã của bạn:
let imageView = UIImageView()
let image = UIImage(color: .red) // (*)
imageView.image = image
imageView.replace(color: .red, withColor: .green)
(*) tạo ra hình ảnh với màu sắc được giải thích here.
Có, thay thế màu hoàn hảo là có thể, nhưng nó sẽ không thực sự hoạt động trong dữ liệu video thế giới thực. Xem câu hỏi này để biết thêm thông tin và giải pháp thực tế: https://stackoverflow.com/questions/18452808/gpuimage-masking-transparency – MoDJ