Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge transparent PNG Image with color

I tried with drawInRect and CGContextDrawImage but it is applying to the whole image.

I want it to apply to the image part only, not to the transparent part. Does anyone know how to do it?

like image 625
Vinay Putta Avatar asked May 24 '13 07:05

Vinay Putta


1 Answers

You can use UIImage with alpha channel as mask for drawing.

Objective-C

- (UIImage *)overlayImage:(UIImage *)image withColor:(UIColor *)color
{
    //  Create rect to fit the PNG image
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

    //  Start drawing
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    //  Fill the rect by the final color
    [color setFill];
    CGContextFillRect(context, rect);

    //  Make the final shape by masking the drawn color with the images alpha values
    CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
    [image drawInRect:rect blendMode:kCGBlendModeDestinationIn alpha:1];

    //  Create new image from the context
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

    //  Release context
    UIGraphicsEndImageContext();

    return img;
}

Example usage:

UIImage *pngImage = [UIImage imageNamed:@"myImage"];
UIColor *overlayColor = [UIColor magentaColor];

UIImage *image = [self overlayImage:pngImage withColor:overlayColor];

Swift 3

extension UIImage {

    func overlayed(by overlayColor: UIColor) -> UIImage {
        //  Create rect to fit the image
        let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)

        // Create image context. 0 means scale of device's main screen
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        let context = UIGraphicsGetCurrentContext()!

        //  Fill the rect by the final color
        overlayColor.setFill()
        context.fill(rect)

        //  Make the final shape by masking the drawn color with the images alpha values
        self.draw(in: rect, blendMode: .destinationIn, alpha: 1)

        //  Create new image from the context
        let overlayedImage = UIGraphicsGetImageFromCurrentImageContext()!

        //  Release context
        UIGraphicsEndImageContext()

        return overlayedImage
    }
}

Example usage:

let overlayedImage = myImage.overlayed(by: .magenta)

Edit: as Desdenova pointed out in the comment, I misunderstood the question. My original answer was drawing the PNG over a colored background. Answer edited, code below is the original one.

- (UIImage *)combineImage:(UIImage *)image withBackgroundColor:(UIColor *)bgColor
{
    //  Create rect to fit the PNG image
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

    //  Create bitmap contect
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    // Draw background first

    //  Set background color (will be under the PNG)
    [bgColor setFill];

    //  Fill all context with background image
    CGContextFillRect(context, rect);

    //  Draw the PNG over the background
    [image drawInRect:rect];

    //  Create new image from the context
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

    //  Release context
    UIGraphicsEndImageContext();

    return img;
}
like image 172
Lukas Kukacka Avatar answered Sep 22 '22 06:09

Lukas Kukacka