Core Image CIColorControls亮度滤镜会产生错误的效果。如何更改图像的亮度?

时间:2012-11-25 00:56:53

标签: ios ios5 graphics core-graphics core-image

我正在为iOS创建颜色选择器。我想让用户选择亮度(亮度)并让色轮反映这种变化。我正在使用Core Image通过CIColorControls过滤器修改亮度。这是我的代码:

-(CIImage *)oldPhoto:(CIImage *)img withBrightness:(float)intensity
{
    CIFilter *lighten = [CIFilter filterWithName:@"CIColorControls"];
    [lighten setValue:img forKey:kCIInputImageKey];
    [lighten setValue:@((intensity * 2.0) - 1.0) forKey:@"inputBrightness"];
    return lighten.outputImage;
}

以下是色轮在强度= 0.5(inputBrightness = 0)时的外观:

My image with inputBrightness = 0

问题是当强度<100时,色轮看起来不对劲。 0.5。例如,这是它在强度= 0.3(inputBrightness = -0.4)时的外观:

My image with inputBrightness = -0.4

请注意,中间有一个黑色圆圈,图像的其余部分也没有正确变暗。这应该是一个HSL色轮,所以我想我真正想要改变的是亮度,而不是亮度。

首先,任何人都可以解释为什么图像看起来像这样?我不是色彩方面的专家;看起来很奇怪,圆圈的中心快速剪成黑色,而它的边缘不会变暗。

其次,我怎样才能达到我想要的效果?

以下是我实际想要看图像的方式:

Image with luminance = 0.3, generated with HSL function on CPU (too slow)

这是使用自定义HSL函数创建的,亮度= 0.3。这在CPU上运行,因此对我的需求来说太慢了。我很乐意发布这个HSL函数的代码,但我没有包含它,因为它似乎没有立即相关。如果你想看到它,请问。

如果您有任何疑问或有任何疑问,请与我们联系。谢谢!

3 个答案:

答案 0 :(得分:6)

我还发现kCIInputBrightnessKey CIColorControls的非线性很烦人。我使用了线性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];
}

这是您的图像,使用上述例程将亮度降低30%:

reduced

可以使用CIToneCurve完成。无论它比你的日常工作更快,你都会有它的基准。

答案 1 :(得分:2)

尝试此操作并使用滑块更改值: -

- (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];
}

答案 2 :(得分:2)

您的CIColorControls过滤器按设计运行。它只是将亮度参数添加到每个像素的红色,绿色和蓝色值。如果负亮度采用低于0的像素,则会剪切为黑色。如果正亮度将其推过1,则会将其剪切为白色。 (实际上,每个频道分别剪辑......)

另一个问题是CIColorControls在RGB色彩空间中工作。 HSL非常不同。这就是为什么你的基色轮与标准的Apple颜色选择器看起来非常不同。

Useful reference