How to programmatically change the hue of UIImage?

后端 未结 5 838
南笙
南笙 2020-12-01 01:26

I am very new to the image processing. I have to implement hue effect in my iPhone application project. Therefore, I need to change the hue of UIImage. Please p

相关标签:
5条回答
  • 2020-12-01 01:26

    In Apple's Swift blog, I came across this photo filtering app tutorial: 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.

    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)
    }
    
    0 讨论(0)
  • 2020-12-01 01:32

    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.

    Hue changes

    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. This is derived from Nitish's solution, although I found that making saturation less than 1.0 had inconsistent results. This method does allow varying the alpha, but for true saturation other than 100% you will probably need a second round of drawing.

    - (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. The code below converts the UIImage to a CIImage, and then converts the result back to UIImage for display. 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.

    // #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;
    }
    
    0 讨论(0)
  • 2020-12-01 01:46
    - (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();    
    }
    
    0 讨论(0)
  • 2020-12-01 01:47

    Swift version of Dondragmer's rotating code above

    // 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!
    }
    
    0 讨论(0)
  • 2020-12-01 01:48

    Taking Dondragmer's excellent fixed hue example as a starting point. 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?

    CGContextClipToMask UIImage Mask Invert Up and Down

    0 讨论(0)
提交回复
热议问题