Multiple CIFilters in one CIImage?
Asked Answered
P

2

5

I have two CIFilters, exposure and hue. I need to combine the filters over one UIImage. How should i go about this? Below is some code that i have so far...

CIFilter *hueFilter;
CIFilter *exposureFilter;
CIImage *adjustedImage;

hueFilter = [CIFilter filterWithName:@"CIHueAdjust"];
exposureFilter = [CIFilter filterWithName:@"CIExposureAdjust"];
[hueFilter setValue:[NSNumber numberWithFloat:5] forKey: @"inputAngle"];
[exposureFilter setValue:[NSNumber numberWithFloat:5] forKey: @"inputEV"];

adjustedImage = [CIImage imageWithCGImage:inputCGImage];
[hueFilter setValue:adjustedImage forKey:@"inputImage"];
[exposureFilter setValue:adjustedImage forKey:@"inputImage"];
Population answered 26/12, 2013 at 1:43 Comment(1)
See also this similar question with Swift examples.Giesser
R
8

Core Image filters can be chained together, one after the other. I find the code easier to read (and write) if it’s written with that idea.

CIFilter *hueFilter;
CIFilter *exposureFilter;
CIImage *inputImage; // assume this has already been created
CIImage *outputImage;

hueFilter = [CIFilter filterWithName:@"CIHueAdjust"];
[hueFilter setValue:inputImage forKey:kCIInputImageKey];
[hueFilter setValue:[NSNumber numberWithFloat:5] forKey:@"inputAngle"];
outputImage = [hueFilter valueForKey:kCIOutputImageKey];

exposureFilter = [CIFilter filterWithName:@"CIExposureAdjust"];
[exposureFilter setValue:outputImage forKey:kCIInputImageKey];
[exposureFilter setValue:[NSNumber numberWithFloat:5] forKey:@"inputEV"];
outputImage = [exposureFilter valueForKey:kCIOutputImageKey];

Above, the first filter is created. Note the use of the constants for the keys where available. At the end of the block the filter has been set for the image, but the calculations are not actually performed until the image is rendered. Any new filters applied will be combined for the most efficient operation.

The next block then applies the next filter, using the output of the first filter as the input for the second. This can be repeated as many times as needed. By writing the code as above, you can easily turn on/off filters as needed, or even reorder them if you have several.

Apple’s documentation is very good and has many examples: Core Image Programming Guide.

Raphael answered 29/12, 2013 at 16:44 Comment(2)
This is not filter chaining; you're simply using as input to the second filter the output of the first.Metabolism
@james-bush That is literally Apple's definition of a filter chain, see for example Chaining Filters for Complex Effects and Create a CI Filter Chain.Raphael
M
2

Here's the easiest and most concise way to chain Core Image filters without recursion:

NSDictionary *filters = @{
                                  @"CIScreenBlendMode" : @{kCIInputImageKey : inputImage, kCIInputBackgroundImageKey : inputImage},
                                  @"CIOverlayBlendMode" : @{kCIInputImageKey : inputImage, kCIInputBackgroundImageKey : inputImage},
                                  @"CIMultiplyBlendMode" : @{kCIInputImageKey : inputImage, kCIInputBackgroundImageKey : inputImage}
                                  };
        [filters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            inputImage = [inputImage imageByApplyingFilter:key withInputParameters:obj];
        }];

You supply the CIImage (inputImage in the sample code above), and then populate the NSDictionary with the name of the filter as the key, and another NSDictionary (which contains the input parameters for the filter) as the object.

The code above enumerates the key-object pairs in the NSDictionary; each pair is used to supply the parameters required by the CIImage imageByApplyingFilter:withInputParameters method.

Metabolism answered 14/3, 2018 at 23:53 Comment(1)
Important note from the docs: This method, though convenient, is inefficient if used multiple times in succession. Achieve better performance by chaining filters without asking for the outputs of individual filters.Chiccory

© 2022 - 2024 — McMap. All rights reserved.