Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I apply a CIFilter to a UIImage?

My app is crashing when I attempt to apply a filter to my user-selected UIImage (It has been working fine without applying the filter). I added and imported the "CoreImage" framework to my project so I could create filters for user-selected images.

I am attempting to apply the filter by creating a category for UIImage (based on Apple's documentation, and then calling the corresponding method on the UIImage selected by the user. Following is the code of my category header and body; what am I doing wrong? (please note, "randColor" is a category UIColor class method to generate a random color)

#import <UIKit/UIKit.h>
#import <CoreImage/CoreImage.h>
#import "UIColor+CustomColorCategory.h"

@interface UIImage (MonoChromeFilter)

- (UIImage *) applyMonoChromeWithRandColor;

@end

#import "UIImage+MonoChromeFilter.h"

@implementation UIImage (MonoChromeFilter)

- (UIImage *)applyMonoChromeWithRandColor
{
    CIContext *context = [CIContext contextWithOptions:nil];

    CIImage *ciImage = [[CIImage alloc] initWithImage:self];

    CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome"];

    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:[UIColor randColor] forKey:kCIAttributeTypeColor];

    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    CGRect extent = [result extent];

    CGImageRef cgImage = [context createCGImage:result fromRect:extent];

    UIImage *filteredImage = [[UIImage alloc] initWithCGImage:cgImage];

    return filteredImage;
}

@end

Here is the method in the viewController where this category is being called:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissViewControllerAnimated:YES completion:^{
        UIImage *editedImage = [info objectForKey:UIImagePickerControllerEditedImage];
        editedImage = [editedImage applyMonoChromeWithRandColor];

        self.blogImageOutlet.image = editedImage;
        self.blogImageOutlet.layer.cornerRadius = self.blogImageOutlet.frame.size.width / 2.0;
        [self.blogImageOutlet setClipsToBounds:YES];

        [self saveImageToLibrary:editedImage];

    }];
}
like image 542
Josh Winskill Avatar asked May 26 '14 07:05

Josh Winskill


People also ask

How do you add a UIImage in Objective C?

UIImage *img = [[UIImage alloc] init]; [img setImage:[UIImage imageNamed:@"anyImageName"]];

What is the difference between UIImage and UIImageView?

UIImage contains the data for an image. UIImageView is a custom view meant to display the UIImage .

What is CIContext?

Overview. The CIContext class provides an evaluation context for Core Image processing with Quartz 2D, Metal, or OpenGL. You use CIContext objects in conjunction with other Core Image classes, such as CIFilter , CIImage , and CIColor , to process images using Core Image filters.

How do I copy UIImage?

Deep copying UIImage *newImage = [UIImage imageWithData:UIImagePNGRepresentation(oldImage)]; This will copy the data but will require setting the orientation property before handing it to something like UIImageView for proper display. Another way to deep copy would be to draw into the context and grab the result.


1 Answers

I figured it out! After debugging and using some other projects as a point of reference, I realized that I was experiencing two issues. First, I was trying to use a UIColor for CIColor, which is not directly possible. I first had to covert the UIColor to a CIColor to be able to apply it. Next, I was not using the correct strings for the CIFilter value keys. Here is the following code after modifications (and now it works!)

#import "UIImage+MonoChromeFilter.h"

@implementation UIImage (MonoChromeFilter)

+ (UIImage *) applyMonoChromeWithRandColor: (UIImage *)uIImage
{

    //  Convert UIColor to CIColor
    CGColorRef colorRef = [UIColor randColor].CGColor;
    NSString *colorString = [CIColor colorWithCGColor:colorRef].stringRepresentation;
    CIColor *coreColor = [CIColor colorWithString:colorString];

    CIContext *context = [CIContext contextWithOptions:nil];

    //  Convert UIImage to CIImage
    CIImage *ciImage = [[CIImage alloc] initWithImage:uIImage];

    //  Set values for CIColorMonochrome Filter
    CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@1.0 forKey:@"inputIntensity"];
    [filter setValue:coreColor forKey:@"inputColor"];

    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    CGRect extent = [result extent];

    CGImageRef cgImage = [context createCGImage:result fromRect:extent];

    UIImage *filteredImage = [[UIImage alloc] initWithCGImage:cgImage];

    return filteredImage;
}

@end
like image 107
Josh Winskill Avatar answered Oct 20 '22 03:10

Josh Winskill