Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use CIColorMatrix in iOS5?

I'm trying to find out how to change the color/hue of a UIImage. I found out that iOS5 has a lot of image filters, but I have hard time finding documentation on the proper use of the CIColorMatrix filter.

-(void)doCIColorMatrixFilter
{

    //does not work, returns nil image
    CIImage* inputImage = [CIImage imageWithCGImage:[[UIImage imageNamed:@"button.jpg"]CGImage]];

    CIFilter *myFilter;
    NSDictionary *myFilterAttributes;
    myFilter = [CIFilter filterWithName:@"CIColorMatrix"];
    [myFilter setDefaults];

    myFilterAttributes = [myFilter attributes];

    [myFilterAttributes setValue:inputImage forKey:@"inputImage"];
    //How to set up attributes?

    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *ciimage = [myFilter outputImage];
    CGImageRef cgimg = [context createCGImage:ciimage fromRect:[ciimage extent]];
    UIImage *uimage = [UIImage imageWithCGImage:cgimg scale:1.0f orientation:UIImageOrientationUp];
    [imageView setImage:uimage];
    CGImageRelease(cgimg);

}

What code goes into the dictionary for this filter?

like image 883
Alex Stone Avatar asked Feb 27 '12 21:02

Alex Stone


2 Answers

One month later ...

This is an example of CIColorMatrix setting all its parameters :)

-(void)doCIColorMatrixFilter
{
    // Make the input image recipe
    CIImage *inputImage = [CIImage imageWithCGImage:[UIImage imageNamed:@"facedetectionpic.jpg"].CGImage]; // 1

    // Make the filter
    CIFilter *colorMatrixFilter = [CIFilter filterWithName:@"CIColorMatrix"]; // 2
    [colorMatrixFilter setDefaults]; // 3
    [colorMatrixFilter setValue:inputImage forKey:kCIInputImageKey]; // 4
    [colorMatrixFilter setValue:[CIVector vectorWithX:1 Y:1 Z:1 W:0] forKey:@"inputRVector"]; // 5
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:1 Z:0 W:0] forKey:@"inputGVector"]; // 6
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:0 Z:1 W:0] forKey:@"inputBVector"]; // 7
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:1] forKey:@"inputAVector"]; // 8

    // Get the output image recipe
    CIImage *outputImage = [colorMatrixFilter outputImage];  // 9

    // Create the context and instruct CoreImage to draw the output image recipe into a CGImage
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; // 10

    // Draw the image in screen
    UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:cgimg]];
    CGRect f = imageView2.frame;
    f.origin.y = CGRectGetMaxY(imageView.frame);
    imageView2.frame = f;

    [self.view addSubview:imageView2];
}

So this is what the sample does:

In 1 we create the ciimage, if you are getting nil there then make sure you are passing the right UIImage/CGImage or path.

In 2 create the filter, you know this :)

In 3 set the filter parameters to its defaults, CoreImage Programming guide suggests we should do this although (I haven't experimented any strange/bad things if avoided.)

In 4 set the input ciimage

From 5 through 8 we set the parameters. For example I made the red vector {1,1,1,0} so the image looks reddish. 6, 7 and 8 and not necessary here since their values are the same as the defaults (remember we called -setDefaults?) but for educational purposes I guess they are fine :)

In 9 set the output image, although is not drawn yet.

Finally in 10 you tell CoreImage to draw the output image into a CGImage, and we put that CGImage into an UIImage and it inside an UIImageView.

This is the result (I used the same image as this tutorial):

Reddish

Hope it helps.

like image 179
nacho4d Avatar answered Sep 28 '22 15:09

nacho4d


Just a Swift example with a chain to add to above answer by nacho4d

var output = CIFilter(name: "CIColorControls")
output.setValue(ciImage, forKey: kCIInputImageKey)
output.setValue(1.8, forKey: "inputSaturation")
output.setValue(0.01, forKey: "inputBrightness")

filter = CIFilter(name: "CIColorMatrix")
filter.setDefaults()
filter.setValue(output.outputImage, forKey: kCIInputImageKey)
filter.setValue(CIVector(x: 1, y: 0.1, z: 0.1, w: 0), forKey: "inputRVector")
filter.setValue(CIVector(x: 0, y: 1, z: 0, w: 0), forKey: "inputGVector")
filter.setValue(CIVector(x: 0, y: 0, z: 1, w: 0), forKey: "inputBVector")

Note that the defaults are 1,0,0 0,1,0 and 0,0,1 respectively for RGB and if you want to make it more red you would set the inputRVector to 1,1,1 and leave the others the same (as this multiples the blue and green components by red values)

like image 45
Aggressor Avatar answered Sep 28 '22 16:09

Aggressor