hzxu
hzxu

Reputation: 5823

iOS: create an darker version of UIImage and leave transparent pixels unchanged?

I found

Create new UIImage by adding shadow to existing UIImage

and

UIImage, is there an easy way to make it darker or all black

But the selected answers do not work for me.

I have an UIImage, which may have some transparent pixels in it, I need to create a new UIImage with non-transparent pixels darkened, is there any way to do this? I was thinking of using UIBezierPath but I don't know how to do it for only non-transparent pixels.

Upvotes: 14

Views: 13746

Answers (4)

Andy
Andy

Reputation: 1865

Here's David's answer in Swift 5:

class func colorizeImage(_ image: UIImage?, with color: UIColor?) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(image?.size ?? CGSize.zero, _: false, _: image?.scale ?? 0.0)

    let context = UIGraphicsGetCurrentContext()
    let area = CGRect(x: 0, y: 0, width: image?.size.width ?? 0.0, height: image?.size.height ?? 0.0)

    context?.scaleBy(x: 1, y: -1)
    context?.translateBy(x: 0, y: -area.size.height)

    context?.saveGState()
    context?.clip(to: area, mask: (image?.cgImage)!)

    color?.set()
    context?.fill(area)

    context?.restoreGState()

    if let context = context {
        context.setBlendMode(.multiply)
    }

    context!.draw((image?.cgImage)!, in: area)

    let colorizedImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return colorizedImage
}

Upvotes: -2

worthbak
worthbak

Reputation: 355

Here's a quick Swift version, using a CIExposureAdjust CIFilter :)

  // Get the original image and set up the CIExposureAdjust filter
  guard let originalImage = UIImage(named: "myImage"),
    let inputImage = CIImage(image: originalImage),
    let filter = CIFilter(name: "CIExposureAdjust") else { return }

  // The inputEV value on the CIFilter adjusts exposure (negative values darken, positive values brighten)
  filter.setValue(inputImage, forKey: "inputImage")
  filter.setValue(-2.0, forKey: "inputEV")

  // Break early if the filter was not a success (.outputImage is optional in Swift)
  guard let filteredImage = filter.outputImage else { return }

  let context = CIContext(options: nil)
  let outputImage = UIImage(CGImage: context.createCGImage(filteredImage, fromRect: filteredImage.extent))

  myImageView.image = outputImage // use the filtered UIImage as required.

Upvotes: 11

David Skrundz
David Skrundz

Reputation: 13347

This is the class I use to color images even if they are transparent.

+ (UIImage *)colorizeImage:(UIImage *)image withColor:(UIColor *)color {
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect area = CGRectMake(0, 0, image.size.width, image.size.height);

    CGContextScaleCTM(context, 1, -1);
    CGContextTranslateCTM(context, 0, -area.size.height);

    CGContextSaveGState(context);
    CGContextClipToMask(context, area, image.CGImage);

    [color set];
    CGContextFillRect(context, area);

    CGContextRestoreGState(context);

    CGContextSetBlendMode(context, kCGBlendModeMultiply);

    CGContextDrawImage(context, area, image.CGImage);

    UIImage *colorizedImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return colorizedImage;
}

To darken the image you would pass the method a black or gray UIColor with lowered transparency.

Upvotes: 33

brynbodayle
brynbodayle

Reputation: 6626

How about trying a CoreImage Filter?

You could use the CIColorControls filter to adjust the input brightness and contrast to darken the image.

CIContext *context = [CIContext contextWithOptions:nil];
CIImage *inputImage = [[CIImage alloc] initWithImage:sourceImage]; //your input image

CIFilter *filter= [CIFilter filterWithName:@"CIColorControls"];
[filter setValue:inputImage forKey:@"inputImage"];
[filter setValue:[NSNumber numberWithFloat:0.5] forKey:@"inputBrightness"];

// Your output image
UIImage *outputImage = [UIImage imageWithCGImage:[context createCGImage:filter.outputImage fromRect:filter.outputImage.extent]];

Read more about the CIFilter parameters here:

http://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CoreImageFilterReference/Reference/reference.html%23//apple_ref/doc/filter/ci/CIColorControls

Upvotes: 16

Related Questions