简体   繁体   English

如何以编程方式更改UIImage的色调?

[英]How to programmatically change the hue of UIImage?

I am very new to the image processing. 我对图像处理很新。 I have to implement hue effect in my iPhone application project. 我必须在我的iPhone应用程序项目中实现hue效果。 Therefore, I need to change the hue of UIImage . 因此,我需要改变UIImage的色调。 Please provide me any sample code or tutorial link for this. 请为我提供任何示例代码或教程链接。

Thanks in advance 提前致谢

First, you need to decide if you are making an image a fixed hue , or rotating the existing hue . 首先,您需要确定是将图像设为固定色调还是旋转现有色调 Examples of both are shown below. 两者的例子如下所示。

色调变化

Fixed hue 固定色调

Fixing the hue can be done using the standard drawing tools - just make sure the blend mode is set to kCGBlendModeHue , and draw with the appropriate hue. 可以使用标准绘图工具修复色调 - 只需确保将混合模式设置为kCGBlendModeHue ,然后使用适当的色调进行绘制。 This is derived from Nitish's solution, although I found that making saturation less than 1.0 had inconsistent results. 这是从Nitish的解决方案中得出的,尽管我发现saturation小于1.0产生不一致的结果。 This method does allow varying the alpha, but for true saturation other than 100% you will probably need a second round of drawing. 此方法允许更改alpha,但对于100%以外的真正饱和度,您可能需要进行第二轮绘制。

- (UIImage*) imageWithImage:(UIImage*) source fixedHue:(CGFloat) hue alpha:(CGFloat) alpha;
// Note: the hue input ranges from 0.0 to 1.0, both red.  Values outside this range will be clamped to 0.0 or 1.0.
{
    // Find the image dimensions.
    CGSize imageSize = [source size];
    CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

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

    // Draw the hue on top of the image.
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [[UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:alpha] set];
    UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
    [imagePath fill];

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

    return result;
}

Rotated hue 旋转的色调

To rotate the hue, you need Core Image filters. 要旋转色调,您需要Core Image滤镜。 The code below converts the UIImage to a CIImage, and then converts the result back to UIImage for display. 下面的代码将UIImage转换为CIImage,然后将结果转换回UIImage进行显示。 Depending on where your image comes from, you may be able to avoid one or both of these steps. 根据图像的来源,您可以避免这些步骤中的一个或两个。

Conveniently, the very first example in the Core Image Programming Guide: Using Core Image Filters uses the CIHueAdjust filter. 方便地,“ 核心映像编程指南:使用核心映像过滤器”中的第一个示例使用CIHueAdjust过滤器。

// #import <CoreImage/CoreImage.h>
// Partially from https://developer.apple.com/library/mac/#documentation/graphicsimaging/conceptual/CoreImaging/ci_tasks/ci_tasks.html
- (UIImage*) imageWithImage:(UIImage*) source rotatedByHue:(CGFloat) deltaHueRadians;
{
    // Create a Core Image version of the image.
    CIImage *sourceCore = [CIImage imageWithCGImage:[source CGImage]];

    // Apply a CIHueAdjust filter
    CIFilter *hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
    [hueAdjust setDefaults];
    [hueAdjust setValue: sourceCore forKey: @"inputImage"];
    [hueAdjust setValue: [NSNumber numberWithFloat: deltaHueRadians] forKey: @"inputAngle"];
    CIImage *resultCore = [hueAdjust valueForKey: @"outputImage"];

    // Convert the filter output back into a UIImage.
    // This section from http://stackoverflow.com/a/7797578/1318452
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef resultRef = [context createCGImage:resultCore fromRect:[resultCore extent]];
    UIImage *result = [UIImage imageWithCGImage:resultRef];
    CGImageRelease(resultRef);

    return result;
}
- (void) changeToHue:(float)hue saturation:(float)saturation {
    UIGraphicsBeginImageContext(self.bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();    
    UIView *hueBlend = [[UIView alloc] initWithFrame:self.bounds];
    hueBlend.backgroundColor = [UIColor colorWithHue:hue saturation:saturation brightness:1 alpha:1];
    CGContextDrawImage(context, self.bounds, self.image.CGImage);
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [hueBlend.layer renderInContext:context];
    self.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();    
}

Taking Dondragmer's excellent fixed hue example as a starting point. 以Dondragmer优秀的固定色调为例作为起点。 Here is my modification, to fix the problem of transparent areas being set with the same hue. 这是我的修改,以解决使用相同色调设置的透明区域的问题。

- (UIImage*) imageWithImage:(NSString *)name fixedHue:(CGFloat) hue alpha:(CGFloat) alpha;
// Note: the hue input ranges from 0.0 to 1.0, both red.  Values outside this range will be clamped to 0.0 or 1.0.
{
    UIImage *source = [UIImage imageNamed:name];

    // Find the image dimensions.
    CGSize imageSize = [source size];
    CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

    // Create a context containing the image.
    UIGraphicsBeginImageContext(imageSize);
    CGContextRef context = UIGraphicsGetCurrentContext();

    [source drawAtPoint:CGPointMake(0,0)];

    // Setup a clip region using the image
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, source.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextClipToMask(context, imageExtent, source.CGImage);

    //[[UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:alpha] set];
    CGContextFillRect(context, imageExtent);

    // Draw the hue on top of the image.
    CGContextDrawImage(context, imageExtent, source.CGImage);
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [[UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:alpha] set];
    UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
    [imagePath fill];

    CGContextRestoreGState(context); // remove clip region

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

    return result;
}

Thanks to: 谢谢:

How to change hue of UIIMAGE having transparent area? 如何改变具有透明区域的UIIMAGE的色调?

CGContextClipToMask UIImage Mask Invert Up and Down CGContextClipToMask UIImage掩码反转向上和向下

In Apple's Swift blog, I came across this photo filtering app tutorial: https://developer.apple.com/swift/blog/?id=16 在Apple的Swift博客中,我遇到了这个照片过滤应用程序教程: https//developer.apple.com/swift/blog/?id = 16

The following is the sample code edited to create a contained method that returns a UIImage with a random hue applied. 以下是编辑的示例代码,用于创建一个包含应用随机色调的UIImage的包含方法。

func applyHue(source: UIImage) -> UIImage {
    // Create a place to render the filtered image
    let context = CIContext(options: nil)

    // Create an image to filter
    let inputImage = CIImage(image: source)

    // Create a random color to pass to a filter
    let randomColor = [kCIInputAngleKey: (Double(arc4random_uniform(314)) / 100)]

    // Apply a filter to the image
    let filteredImage = inputImage!.imageByApplyingFilter("CIHueAdjust", withInputParameters: randomColor)

    // Render the filtered image
    let renderedImage = context.createCGImage(filteredImage, fromRect: filteredImage.extent)

    // Return a UIImage
    return UIImage(CGImage: renderedImage)
}

Swift version of Dondragmer's rotating code above Swift版本的Dondragmer上面的旋转代码

// Convert the filter output back into a UIImage.
// This section from http://stackoverflow.com/a/7797578/1318452
func imageWithImage(source: UIImage, rotatedByHue: CGFloat) -> UIImage {
    // Create a Core Image version of the image.
    let sourceCore = CIImage(CGImage: source.CGImage)
    // Apply a CIHueAdjust filter
    let hueAdjust = CIFilter(name: "CIHueAdjust")
    hueAdjust.setDefaults()
    hueAdjust.setValue(sourceCore, forKey: "inputImage")
    hueAdjust.setValue(CGFloat(rotatedByHue), forKey: "inputAngle")
    let resultCore  = hueAdjust.valueForKey("outputImage") as CIImage!
    let context = CIContext(options: nil)
    let resultRef = context.createCGImage(resultCore, fromRect: resultCore!.extent())
    let result = UIImage(CGImage: resultRef)
    return result!
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM