如何改变具有透明区域的UIIMAGE的色调?

3

我目前正在使用以下代码来改变色调:

  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();

这段代码可以运行,唯一的问题是它也会将透明部分的颜色设置为色调。我可以避免将色调应用于UIImage的透明区域吗?
以下是参考两张图片:
谢谢提前!
输出 enter image description here
3个回答

4

在添加颜色之前,从图像中应用掩码。

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();

@maddy 感谢你的帮助,实际上我想把它变成通用代码,而不是针对任何特定的图像。例如,您有衬衫、帽子等透明图像,我只想改变不透明部分的色调。我已经附上了两张图片。 - Deepak Singh Negi
1
这就是我的回答应该做的。 - rmaddy
嘿@rmaddy,谢谢,它正在工作,但我正在尝试修复这个180度旋转的遮罩图像问题,使用CGContextRotateCTM,但它不改变色调。你能帮忙吗? - Deepak Singh Negi
1
旋转将围绕角落的原点发生,而不是中心。因此,您需要除了旋转之外还要进行平移。 - rmaddy
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
显示剩余2条评论

2

我使用了Core Image来实现你想要的功能。注意:这是用Swift编写的,但你应该能理解。

    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)

注意:根据这篇Stack Overflow帖子,inputAngle的输入是以弧度为单位的。


1
这段代码对我有效。
- (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;
}

@dangerZone 谢谢,我已经做了。 - Fahad Azeem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接