Core Image CIColorControls brightness filter creates wrong effect. How do I change my image's luminance?

前端 未结 3 1318
半阙折子戏
半阙折子戏 2020-12-24 14:48

I\'m creating a color picker for iOS. I would like to enable the user to select the brightness (luminance) and have the color wheel reflect this change. I\'m using Core Imag

相关标签:
3条回答
  • 2020-12-24 15:13

    I also found the non-linearity of the kCIInputBrightnessKey of CIColorControls to be annoying. I employed a linear CIToneCurve:

    /** Change luminosity of `CIImage`
    
     @param inputImage The `CIImage` of the image to have it's luminosity changed.
     @param luminosity The percent change of the luminosity, ranging from -1.0 to 1.0.
    
     @return `CIImage` of image with luminosity changed. If luminosity of 0.0 used, original `inputImage` is returned.
     */
    
    - (CIImage *)changeLuminosityOfCIImage:(CIImage *)inputImage luminosity:(CGFloat)luminosity
    {
        if (luminosity == 0)
            return inputImage;
    
        NSParameterAssert(luminosity >= -1.0 && luminosity <= 1.0);
    
        CIFilter *toneCurveFilter = [CIFilter filterWithName:@"CIToneCurve"];
        [toneCurveFilter setDefaults];
        [toneCurveFilter setValue:inputImage forKey:kCIInputImageKey];
    
        if (luminosity > 0)
        {
            [toneCurveFilter setValue:[CIVector vectorWithX:0.0  Y:luminosity]                           forKey:@"inputPoint0"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:luminosity + 0.25 * (1 - luminosity)] forKey:@"inputPoint1"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:luminosity + 0.50 * (1 - luminosity)] forKey:@"inputPoint2"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:luminosity + 0.75 * (1 - luminosity)] forKey:@"inputPoint3"];
            [toneCurveFilter setValue:[CIVector vectorWithX:1.0  Y:1.0]                                  forKey:@"inputPoint4"];
        }
        else
        {
            [toneCurveFilter setValue:[CIVector vectorWithX:0.0  Y:0.0]                     forKey:@"inputPoint0"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:0.25 * (1 + luminosity)] forKey:@"inputPoint1"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:0.50 * (1 + luminosity)] forKey:@"inputPoint2"];
            [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:0.75 * (1 + luminosity)] forKey:@"inputPoint3"];
            [toneCurveFilter setValue:[CIVector vectorWithX:1.0  Y:1 + luminosity]          forKey:@"inputPoint4"];
        }
    
        return [toneCurveFilter outputImage];
    }
    

    Here is your image, reducing the luminosity by 30% using the above routine:

    reduced

    It can be done with CIToneCurve. Whether it's faster than your routine, you'll have benchmark it.

    0 讨论(0)
  • 2020-12-24 15:25

    Your CIColorControls filter is working as designed. It simply adds it's brightness parameter to the red, green, and blue values of each pixel. If a negative brightness takes the pixel below 0, it clips to black. If a positive brightness pushes it over 1, it clips to white. (Actually, each channel clips separately...)

    Another issue is that CIColorControls works in RGB color space. HSL is very different. This is why your base color wheel looks very different from the standard Apple color picker.

    Useful reference

    0 讨论(0)
  • 2020-12-24 15:27

    Try this and change value using a slider:-

    - (void)viewDidLoad{
    
       UIImage *aUIImage = showPickedImageView.image;
       CGImageRef aCGImage = aUIImage.CGImage;
       aCIImage = [CIImage imageWithCGImage:aCGImage];
    
    
       context = [[CIContext contextWithOptions:nil] retain];
       brightnessFilter = [[CIFilter filterWithName:@"CIColorControls" keysAndValues: @"inputImage", aCIImage, nil] retain];
    
    }
    
    - (IBAction)brightnessSliderValueChanged:(id)sender {
    
        [brightnessFilter setValue:[NSNumber numberWithFloat:brightnessSlider.value ] forKey: @"inputBrightness"];
        outputImage = [brightnessFilter outputImage];
        CGImageRef cgiig = [context createCGImage:outputImage fromRect:[outputImage extent]];
        newUIImage = [UIImage imageWithCGImage:cgiig];
        CGImageRelease(cgiig);
        [showPickedImageView setImage:newUIImage];
    }
    
    0 讨论(0)
提交回复
热议问题