问题
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:


Thanks in advance?
Output

回答1:
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();
回答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.
回答3:
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;
}
来源:https://stackoverflow.com/questions/24962645/how-to-change-hue-of-uiimage-having-transparent-area