CIFilter guassianBlur and boxBlur are shrinking the image - how to avoid the resizing?

foundry picture foundry · Nov 19, 2012 · Viewed 8.9k times · Source

I am taking a snapshot of the contents of an NSView, applying a CIFilter, and placing the result back into the view. If the CIFilter is a form of blur, such as CIBoxBlur or CIGuassianBlur, the filtered result is slightly smaller than the original. As I am doing this iteratively the result becomes increasingly small, which I want to avoid.

The issue is alluded to here albeit in a slightly different context (Quartz Composer). Apple FunHouse demo app applies a Guassian blur without the image shrinking, but I haven't yet worked out how this app does it (it seems to be using OpenGL which I am not familiar with).

Here is the relevant part of the code (inside an NSView subclass)

NSImage* background = [[NSImage alloc] initWithData:[self dataWithPDFInsideRect:[self bounds]]];

CIContext* context = [[NSGraphicsContext currentContext] CIContext];
CIImage* ciImage = [background ciImage];

 CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"
 keysAndValues: kCIInputImageKey, ciImage,
 @"inputRadius", [NSNumber numberWithFloat:10.0], nil];

CIImage *result = [filter valueForKey:kCIOutputImageKey];
CGImageRef cgImage = [context createCGImage:result
                                   fromRect:[result extent]];

NSImage* newBackground = [[NSImage alloc] initWithCGImage:cgImage size:background.size];

If I try a color-changing filter such as CISepiaTone, which is not shifting pixels around, the shrinking does not occur.

I am wondering if there is a quick fix that doesn't involve diving into openGL?

Answer

BBC_Z picture BBC_Z · Dec 16, 2012

They're actually not shrinking the image, they're expanding it (I think by 7 pixels around all edges) and the default UIView 'scale To View' makes it looks like it's been shrunk.

Crop your CIImage with:

CIImage *cropped=[output imageByCroppingToRect:CGRectMake(0, 0, view.bounds.size.width*scale, view.bounds.size.height*scale)];

where view is the original bounds of your NSView that you drew into and 'scale' is your [UIScreen mainScreen] scale].