Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invert white to black uiimage

Tags:

ios

uiimage

I have the following UIImage:

enter image description here

Using Objective-C, I want to be able to invert the white to black and vice versa.

Any help would be appreciated.

like image 861
Maystro Avatar asked Feb 07 '15 21:02

Maystro


People also ask

How to change image color in Swift?

The absolute simplest way to change colors of images (or icons in this case) is to use the SF Symbols where applicaple. This is a set of symbols Apple provides that can easily be used in your own app. You can download an app to help you find the correct symbol for you needs here.

How do I make a picture black and white in Swift?

If you use gray as your tint color, it produces plain black and white images, but you can also use other colors to get sepia tone and other effects. To make that work you'll need a UIImage called yourUIImage , then replace the print(processedImage.


4 Answers

Swift

Using CIContext instead of -UIImage:CIImage (see https://stackoverflow.com/a/28386697/218152), and building upon @wtznc's response, here is a self-contained IBDesignable:

@IBDesignable
class InvertImage: UIImageView {

    @IBInspectable var originalImage:UIImage? = nil

    @IBInspectable var invert:Bool = false {
        didSet {
            var inverted = false
            if let originalImage = self.originalImage {
                if(invert) {
                    let image = CIImage(CGImage: originalImage.CGImage!)
                    if let filter = CIFilter(name: "CIColorInvert") {
                        filter.setDefaults()
                        filter.setValue(image, forKey: kCIInputImageKey)
                        
                        let context = CIContext(options: nil)
                        let imageRef = context.createCGImage(filter.outputImage!, fromRect: image.extent)
                        self.image = UIImage(CGImage: imageRef)
                        inverted = true
                    }
                }
            }
            
            if(!inverted) {
                self.image = self.originalImage
            }
        }
    }
}

To use it, set Original Image instead of Image since Image will be dynamically associated:

enter image description here

like image 175
SwiftArchitect Avatar answered Oct 23 '22 05:10

SwiftArchitect


Swift3

extension UIImage {
    func invertedImage() -> UIImage? {
        guard let cgImage = self.cgImage else { return nil }
        let ciImage = CoreImage.CIImage(cgImage: cgImage)
        guard let filter = CIFilter(name: "CIColorInvert") else { return nil }
        filter.setDefaults()
        filter.setValue(ciImage, forKey: kCIInputImageKey)
        let context = CIContext(options: nil)
        guard let outputImage = filter.outputImage else { return nil }
        guard let outputImageCopy = context.createCGImage(outputImage, from: outputImage.extent) else { return nil }
        return UIImage(cgImage: outputImageCopy, scale: self.scale, orientation: .up) 
    }
}
like image 42
neoneye Avatar answered Oct 23 '22 06:10

neoneye


- (UIImage *)negativeImage
{
    // get width and height as integers, since we'll be using them as
    // array subscripts, etc, and this'll save a whole lot of casting
    CGSize size = self.size;
    int width = size.width;
    int height = size.height;

    // Create a suitable RGB+alpha bitmap context in BGRA colour space
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *memoryPool = (unsigned char *)calloc(width*height*4, 1);
    CGContextRef context = CGBitmapContextCreate(memoryPool, width, height, 8, width * 4, colourSpace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);

    // draw the current image to the newly created context
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);

    // run through every pixel, a scan line at a time...
    for(int y = 0; y < height; y++)
    {
        // get a pointer to the start of this scan line
        unsigned char *linePointer = &memoryPool[y * width * 4];

        // step through the pixels one by one...
        for(int x = 0; x < width; x++)
        {
            // get RGB values. We're dealing with premultiplied alpha
            // here, so we need to divide by the alpha channel (if it
            // isn't zero, of course) to get uninflected RGB. We
            // multiply by 255 to keep precision while still using
            // integers
            int r, g, b;
            if(linePointer[3])
            {
                r = linePointer[0] * 255 / linePointer[3];
                g = linePointer[1] * 255 / linePointer[3];
                b = linePointer[2] * 255 / linePointer[3];
            }
            else
                r = g = b = 0;

            // perform the colour inversion
            r = 255 - r;
            g = 255 - g;
            b = 255 - b;

            if ( (r+g+b) / (3*255) == 0 )
            {

                linePointer[0] = linePointer[1] = linePointer[2] = 0;
                linePointer[3] = 0;
            }
            else
            {
                // multiply by alpha again, divide by 255 to undo the
                // scaling before, store the new values and advance
                // the pointer we're reading pixel data from
                linePointer[0] = r * linePointer[3] / 255;
                linePointer[1] = g * linePointer[3] / 255;
                linePointer[2] = b * linePointer[3] / 255;

            }
            linePointer += 4;
        }
    }

    // get a CG image from the context, wrap that into a
    // UIImage
    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    UIImage *returnImage = [UIImage imageWithCGImage:cgImage];

    // clean up
    CGImageRelease(cgImage);
    CGContextRelease(context);
    free(memoryPool);

    // and return
    return returnImage;
}

I added the above method inside a UIImage extension class.

like image 5
Maystro Avatar answered Oct 23 '22 06:10

Maystro


Firstly, you have to add the Core Image framework to your project.

Project settings -> Targets "project name" -> Build phases -> Link Binary With Libraries -> Add items -> CoreImage.framework

enter image description here Secondly, import the Core Image header to your implementation file.

#import <CoreImage/CoreImage.h>

Initialize an UIImage object to store the original file.

UIImage *inputImage = [UIImage imageNamed:@"imageNamed"];

Create a CIFilter to define how you want to modify your original UIImage object.

CIFilter* filter = [CIFilter filterWithName:@"CIColorInvert"];
[filter setDefaults];
[filter setValue:inputImage.CIImage forKey:@"inputImage"];

Create another UIImage object to keep modified image.

UIImage *outputImage = [[UIImage alloc] initWithCIImage:filter.outputImage];

Voilà! Hope it will help.

like image 4
wtznc Avatar answered Oct 23 '22 06:10

wtznc