Franhu
Franhu

Reputation: 63

Invert colors of image with transparent background

I have an uiimage with transparent background. if I invert the colors with the follow method, the transparent background change to white and then to black.

I want that it doesnt invert transparent pixels? how can i do that?

- (UIImage *) getImageWithInvertedPixelsOfImage:(UIImage *)image {
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 2);
    CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference);
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor whiteColor].CGColor);
    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height));
    UIImage * result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Upvotes: 3

Views: 4019

Answers (3)

Steve
Steve

Reputation: 11

This is a Swift 4.0 version of @maggix answer...

func invertImage(with originalImage: UIImage) -> UIImage? {
    var image: UIImage?
    UIGraphicsBeginImageContext(originalImage.size)
    if let context = UIGraphicsGetCurrentContext() {
        context.setBlendMode(.copy)
        let imageRect = CGRect(x: 0, y: 0, width: originalImage.size.width, height: originalImage.size.height)
        originalImage.draw(in: imageRect)
        context.setBlendMode(.difference)
        // translate/flip the graphics context (for transforming from CG* coords to UI* coords
        context.translateBy(x: 0, y: originalImage.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        //mask the image
        context.clip(to: imageRect, mask: originalImage.cgImage!)
        context.setFillColor(UIColor.white.cgColor)
        context.fill(CGRect(x: 0, y:0, width: originalImage.size.width, height: originalImage.size.height))

        image = UIGraphicsGetImageFromCurrentImageContext()
    }
    UIGraphicsEndImageContext()
    return image
}

Upvotes: 1

mxcl
mxcl

Reputation: 26893

I created a Pod from @maggix's answer:

pod 'UIImage+InvertedImage'

Upvotes: 1

maggix
maggix

Reputation: 3278

this is how I solved.

It is the code that you can find in other answers, but with the masking of the current image with the same image, with rotated context (for transforming from CG* coords to UI* coords).

- (UIImage *)invertImage:(UIImage *)originalImage
{
    UIGraphicsBeginImageContext(originalImage.size);
    CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
    CGRect imageRect = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height);
    [originalImage drawInRect:imageRect];


    CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference);
    // translate/flip the graphics context (for transforming from CG* coords to UI* coords
    CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, originalImage.size.height);
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
    //mask the image
    CGContextClipToMask(UIGraphicsGetCurrentContext(), imageRect,  originalImage.CGImage);
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor whiteColor].CGColor);
    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, originalImage.size.width, originalImage.size.height));
    UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return returnImage;
}

Upvotes: 2

Related Questions