2011-08-24 9 views
5

Tengo una imagen de "habitación".Reemplazar un color en particular dentro de una imagen con otro color

Ahora, el usuario hará clic en cualquier color en particular, suponga que el color azul en la imagen.

Y también el usuario seleccionará el color reemplazado como el color "negro".

Por lo tanto, todo el color "azul" dentro de la imagen será reemplazado por el color "negro".

¿Alguien tiene idea de cómo lograr esto en iPhone?

Se agradece la ayuda.

+0

Sí, es posible reemplazar el color perfecto, pero en realidad no funcionará en los datos de video del mundo real. Consulte esta pregunta para obtener más información y una solución real: https://stackoverflow.com/questions/18452808/gpuimage-masking-transparency – MoDJ

Respuesta

6
  1. Tienes que recorrer cada píxel de la imagen y tomar su rgb valores
  2. Compruebe sus valores RGB coincide con sus valores RGB fromColor, en caso afirmativo cambiar el valor del píxel a su RGB toColor values.If no , acaba de salir de ese píxel e ir a la siguiente ..

Has escrito una función de memory..errors possible..correct mismo

-(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; 
} 

Espero que no llame a esta función cada vez ... Es un procesador de poco peso ... Y si fuera su procesador, no estaría contento con usted .. :)

+0

Dint trabajo para mí.no se produjo ningún cambio en el color – Shailesh

+0

@Shailesh, este código se escribió hace años cuando no había una biblioteca de filtrado de imágenes nativas disponible para iOS. iOS ahora tiene un marco de imagen central, y probablemente eso es lo que debes considerar. – Krishnabhadra

+0

Sí ... Lo estoy haciendo. Por cierto ... aquí está la pregunta que había publicado. http://stackoverflow.com/questions/27482508/virtual-wall-walling-like-app-ios Le agradecería si pudiera ayudar – Shailesh

0

Necesitará acceso a los datos en bruto de píxeles de alguna manera (ver this answer o el código del usuario Krishnabhadra). Busque a través de todos los píxeles y, por ejemplo, para el reemplazo azul-> negro, reemplace todos los píxeles azules con negro. Considere la posibilidad de convertir el color a HSV, lo que facilitará el cálculo del reemplazo del color.

0

he modificado un poco de código de Krishnabhadra de, ya que estoy usando para la entrada RGB del color, así como la producción por ejemplo:

[UIColor colorWithRed: 191.0f/255.0f verde: 30.0f/255.0f azul: 45.0 f/255.0f alpha: 1.0f]

Funciona para mí.

-(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;} 
0

Me encontré con esta respuesta en busca de reemplazar un color por otro. Bueno, como necesito el código Swift, lo he intentado varias veces y encuentro una buena solución. Gracias @Rob por su 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 
    } 

} 

Dónde estructura RGBA32 es simplemente:

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 
    } 

} 

De esta manera, siempre que sea en el código:

let imageView = UIImageView() 
let image = UIImage(color: .red) // (*) 
imageView.image = image 
imageView.replace(color: .red, withColor: .green) 

(*) creación de una imagen de color se explica here.

Cuestiones relacionadas