3

I am currently using following code for hue change:

  CGSize imageSize = [imageView.image size];
  CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

  // Create a context containing the image.
  UIGraphicsBeginImageContext(imageSize);
  CGContextRef context = UIGraphicsGetCurrentContext();
  [imageView.image drawAtPoint:CGPointMake(0, 0)];

  // Draw the hue on top of the image.
  CGContextSetBlendMode(context, kCGBlendModeHue);
  [color set];

  UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
  [imagePath fill];

  // Retrieve the new image.
  UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
  imageView.image= result;

  UIGraphicsEndImageContext();

This code is working fine, only issue is it also sets the colour of transparent portions. Can I avoid applying the hue to that transparent area of the UIImage?

Attached following two images for reference:

enter image description here enter image description here

Thanks in advance?

Output enter image description here

3 Answers3

4

Apply a mask from the image before adding the color.

CGSize imageSize = [imageView.image size];
CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

// Create a context containing the image.
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
[imageView.image drawAtPoint:CGPointMake(0, 0)];

// Setup a clip region using the image
CGContextSaveGState(context);
CGContextClipToMask(context, imageExtent, imageView.image.CGImage);

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

// Draw the hue on top of the image.
CGContextSetBlendMode(context, kCGBlendModeHue);
[color set];

UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
[imagePath fill];

CGContextRestoreGState(context); // remove clip region

// Retrieve the new image.
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
imageView.image= result;

UIGraphicsEndImageContext();
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • @maddy thanks for the help actually I want to make it a general code not for any specific image. For example you have shirt, cap etc transparent images, I just want to change hue of the opaque part only. I've attached an two images. – Deepak Singh Negi Jul 26 '14 at 19:30
  • 1
    That's what my answer should do. – rmaddy Jul 26 '14 at 21:47
  • Hey @rmaddy, thanks it's working but I'm trying to fix this issue of 180 rotated masked image , used CGContextRotateCTM but than its not changing the hue. Can you please help? – Deepak Singh Negi Jul 28 '14 at 17:19
  • 1
    The rotation will happen around the origin which is in the corner, not the center. So you will need to translate in addition to rotate. – rmaddy Jul 28 '14 at 17:25
  • I think its only possible through CIFilter but that doesn't change according to selected color. It only changes according to deltaHueRadians in float. But I want to change it by selected color. Any suggestion to fix it? – Deepak Singh Negi Jul 29 '14 at 17:46
  • CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1.0, -1.0); http://stackoverflow.com/questions/8141366/cgcontextcliptomask-uiimage-mask-invert-up-and-down – JonLord Mar 15 '15 at 12:37
  • what is ctx and area ? – abh Sep 08 '16 at 11:16
2

I used Core Image to do what you're trying to achieve. Note: this is in Swift but you should get the gist.

    var hueFilter = CIFilter(name: "CIHueAdjust", withInputParameters: ["inputAngle" : M_2_PI])
    let imageRef = UIImage(named: "Maggie").CGImage
    let coreImage = CIImage(CGImage: imageRef)
    hueFilter.setValue(coreImage, forKey: kCIInputImageKey)
    maggieView.image = UIImage(CIImage: hueFilter.outputImage)

One note: the inputAngle is done in radians according to this SO post.

Community
  • 1
  • 1
SushiGrass Jacob
  • 19,425
  • 1
  • 25
  • 39
1

This code worked for me.

- (UIImage*)imageWithImage:(UIImageView*)source colorValue:(CGFloat)hue {
    CGSize imageSize = [source.image size];
    CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

    // Create a context containing the image.
    UIGraphicsBeginImageContext(imageSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [source.image drawAtPoint:CGPointMake(0, 0)];

    // Setup a clip region using the image
    CGContextSaveGState(context);
    CGContextClipToMask(context, source.bounds, source.image.CGImage);

    self.imageColor = [UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:1.0];
    [self.imageColor set];
    CGContextFillRect(context, source.bounds);

    // Draw the hue on top of the image.
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [self.imageColor set];

    UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
    [imagePath fill];

    CGContextRestoreGState(context); // remove clip region

    // Retrieve the new image.
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}
Fahad Azeem
  • 541
  • 7
  • 14