用另一种颜色replace图像中的特定颜色
我有一个“房间”的形象。
现在,用户将点击任何特定的颜色假设图像中的蓝色。
而且用户也将selectreplace的颜色,如“黑色”的颜色。
因此,图像内的所有“蓝色”颜色将被replace为“黑色”颜色。
任何人有想法如何在iPhone中实现这一点?
帮助表示赞赏。
- 您必须迭代图像中的每个像素并获取其rgb值
- 检查它的rgb值是否匹配你的fromColor rgb值,如果是,则将像素值更改为你的toColor rgb值。如果没有,就离开那个像素并转到下一个值。
从内存写了一个函数..错误可能…纠正自己
-(UIImage*)changeColor:(UIImage*)myImage fromColor:(UIColor*)fromColor toColor:(UIColor*)toColor{ CGImageRef originalImage = [myImage CGImage]; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef bitmapContext = CGBitmapContextCreate(NULL,CGImageGetWidth(originalImage),CGImageGetHeight(originalImage), 8,CGImageGetWidth(originalImage)*4,colorSpace,kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGBitmapContextGetWidth(bitmapContext),CGBitmapContextGetHeight(bitmapContext)), originalImage); UInt8 *data = CGBitmapContextGetData(bitmapContext); int numComponents = 4; int bytesInContext = CGBitmapContextGetHeight(bitmapContext) * CGBitmapContextGetBytesPerRow(bitmapContext); double redIn, greenIn, blueIn,alphaIn; CGFloat fromRed,fromGreen,fromBlue,fromAlpha; CGFloat toRed,toGreen,toBlue,toAlpha; //Get RGB values of fromColor int fromCountComponents = CGColorGetNumberOfComponents([fromColor CGColor]); if (fromCountComponents == 4) { const CGFloat *_components = CGColorGetComponents([fromColor CGColor]); fromRed = _components[0]; fromGreen = _components[1]; fromBlue = _components[2]; fromAlpha = _components[3]; } //Get RGB values for toColor int toCountComponents = CGColorGetNumberOfComponents([toColor CGColor]); if (toCountComponents == 4) { const CGFloat *_components = CGColorGetComponents([toColor CGColor]); toRed = _components[0]; toGreen = _components[1]; toBlue = _components[2]; toAlpha = _components[3]; } //Now iterate through each pixel in the image.. for (int i = 0; i < bytesInContext; i += numComponents) { //rgba value of current pixel.. redIn = (double)data[i]/255.0; greenIn = (double)data[i+1]/255.0; blueIn = (double)data[i+2]/255.0; alphaIn = (double)data[i+3]/255.0; //now you got current pixel rgb values...check it curresponds with your fromColor if( redIn == fromRed && greenIn == fromGreen && blueIn == fromBlue ){ //image color matches fromColor, then change current pixel color to toColor data[i] = toRed; data[i+1] = toGreen; data[i+2] = toBlue; data[i+3] = toAlpha; } } CGImageRef outImage = CGBitmapContextCreateImage(bitmapContext); myImage = [UIImage imageWithCGImage:outImage]; CGImageRelease(outImage); return myImage; }
我希望你不是每次都调用这个函数…这是一个很重的处理器。如果我是你的处理器,我不会对你感到高兴。
您需要以某种方式访问原始像素数据(请参阅此答案或用户Krishnabhadra的代码)。 search所有像素,例如蓝色 – >黑色replace,用黑色replace全部蓝色像素。 看看将颜色转换为HSV,这将使颜色replace计算更容易。
我修改了一点Krishnabhadra的代码,因为我使用RGB作为颜色input以及输出,例如:
[UIColor colorWithRed:191.0f / 255.0f green:30.0f / 255.0f blue:45.0f / 255.0f alpha:1.0f]
为我工作。
-(UIImage*)changeColor:(UIImage*)myImage fromColor:(UIColor*)fromColor toColor:(UIColor*)toColor{ CGImageRef originalImage = [myImage CGImage]; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef bitmapContext = CGBitmapContextCreate(NULL,CGImageGetWidth(originalImage),CGImageGetHeight(originalImage), 8,CGImageGetWidth(originalImage)*4,colorSpace,kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGBitmapContextGetWidth(bitmapContext),CGBitmapContextGetHeight(bitmapContext)), originalImage); UInt8 *data = CGBitmapContextGetData(bitmapContext); int numComponents = 4; int bytesInContext = CGBitmapContextGetHeight(bitmapContext) * CGBitmapContextGetBytesPerRow(bitmapContext); double redIn, greenIn, blueIn,alphaIn; CGFloat fromRed,fromGreen,fromBlue,fromAlpha; CGFloat toRed,toGreen,toBlue,toAlpha; //Get RGB values of fromColor int fromCountComponents = CGColorGetNumberOfComponents([fromColor CGColor]); if (fromCountComponents == 4) { const CGFloat *_components = CGColorGetComponents([fromColor CGColor]); fromRed = _components[0]; fromGreen = _components[1]; fromBlue = _components[2]; fromAlpha = _components[3]; } //Get RGB values for toColor int toCountComponents = CGColorGetNumberOfComponents([toColor CGColor]); if (toCountComponents == 4) { const CGFloat *_components = CGColorGetComponents([toColor CGColor]); toRed = _components[0]*255; toGreen = _components[1]*255; toBlue = _components[2]*255; toAlpha = _components[3]*255; } //Now iterate through each pixel in the image.. for (int i = 0; i < bytesInContext; i += numComponents) { //rgba value of current pixel.. redIn = (double)data[i]; greenIn = (double)data[i+1]; blueIn = (double)data[i+2]; alphaIn = (double)data[i+3]; //now you got current pixel rgb values...check it curresponds with your fromColor if( redIn == fromRed && greenIn == fromGreen && blueIn == fromBlue && alphaIn != 0 ){ //image color matches fromColor, then change current pixel color to toColor data[i] = toRed; data[i+1] = toGreen; data[i+2] = toBlue; data[i+3] = toAlpha; } } CGImageRef outImage = CGBitmapContextCreateImage(bitmapContext); myImage = [UIImage imageWithCGImage:outImage]; CGImageRelease(outImage); return myImage;}
我偶然发现了用另一种replace颜色的答案。 那么,因为我需要的Swift代码,我有几个尝试,我find一个不错的解决scheme。 感谢@Rob的回答 。
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 } }
在哪里RGBA32结构是简单的:
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 } }
通过这种方式,无论你的代码在哪里:
let imageView = UIImageView() let image = UIImage(color: .red) // (*) imageView.image = image imageView.replace(color: .red, withColor: .green)
(*)用颜色创build图像在这里解释。