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

前端 未结 3 1336
半阙折子戏
半阙折子戏 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.

提交回复
热议问题