我有一个“房间”图像。用另一种颜色替换图像中的特定颜色
现在,用户将点击任何特定的颜色假设图像中的蓝色。
而且用户还将选择替换颜色,如“黑色”颜色。
因此,图像内的所有“蓝色”颜色将被替换为“黑色”颜色。
任何人有想法如何在iPhone中实现这一点?
帮助表示赞赏。
我有一个“房间”图像。用另一种颜色替换图像中的特定颜色
现在,用户将点击任何特定的颜色假设图像中的蓝色。
而且用户还将选择替换颜色,如“黑色”颜色。
因此,图像内的所有“蓝色”颜色将被替换为“黑色”颜色。
任何人有想法如何在iPhone中实现这一点?
帮助表示赞赏。
写了一个函数从memory..errors possible..correct自己
-(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;
}
我希望你不会每次都调用这个函数......它有点重要..如果我是你的处理器,我不会对你感到高兴.. :)
Dint为我工作。在颜色 – Shailesh
@Shailesh没有得到任何改变,这个代码是在很多年前写的,当时没有可用于iOS的本地图像过滤库。 iOS现在拥有核心图像框架,可能这就是你应该研究的内容。 – Krishnabhadra
是的..我正在那样做。顺便说一句..这是我发布的问题。 http://stackoverflow.com/questions/27482508/virtual-wall-painting-like-app-ios 我将不胜感激,如果你能帮助 – Shailesh
你需要以某种方式访问原始像素数据(请参阅this answer或用户Krishnabhadra的代码)。搜索所有像素,例如蓝色 - >黑色替换,用黑色替换所有蓝色像素。看看将颜色转换为HSV,这将使颜色替换计算更容易。
我修改了一个小的Krishnabhadra的代码,因为我使用的是RGB颜色输入和输出如:
[的UIColor colorWithRed:191.0f/255.0f绿色:30.0f/255.0f蓝:45.0 f/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;}
我偶然发现了这个答案,寻找用另一种颜色代替颜色。 那么,因为我需要Swift代码,我有几次尝试,我找到了一个很好的解决方案。感谢@Rob的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
}
}
哪里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)
(*)的彩色图像创建解释here。
是的,完美的色彩替换是可能的,但它不会真正在真实世界的视频数据中工作。看到这个问题的更多信息和一个真正的解决方案:https://stackoverflow.com/questions/18452808/gpuimage-masking-transparency – MoDJ