CIFilter guassianBlur и boxBlur уменьшают изображение - как избежать изменения размера?

я делаю снимок содержимого NSView, применяя CIFilter, и размещение результата обратно в представление. Если CIFilter является формой размытия, например CIBoxBlur или CIGuassianBlur, отфильтрованный результат немного меньше, чем оригинал. Поскольку я делаю это итеративно, результат становится все более маленьким, чего я хочу избежать.

этот вопрос упоминается здесь хотя и в несколько ином контексте (Quartz Composer). Яблоко!--6--> демо приложения применяет Guassian blur без сжатия изображения, но я еще не понял, как это приложение делает это (кажется, использует OpenGL С которым я не знаком).

вот соответствующая часть кода (внутри NSView подкласс)

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

если я попробую фильтр изменения цвета, такой как CISepiaTone, который не сдвигает пиксели вокруг, сжатие не происходит.

мне интересно, есть ли быстрое решение, которое не включает погружение в openGL?

3 ответов


они на самом деле не сжимают изображение, они расширяют его (я думаю, на 7 пикселей по всем краям), и по умолчанию UIView "масштаб для просмотра" делает его похожим на сжатие.

обрезать CIImage с:

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

где view-исходные границы вашего NSView, которые вы нарисовали, а "масштаб" - ваш [uiscreen mainScreen] масштаб].


вы, вероятно, хотите зажать изображение перед использованием размытия:

- (CIImage*)imageByClampingToExtent {
    CIFilter *clamp = [CIFilter filterWithName:@"CIAffineClamp"];
    [clamp setValue:[NSAffineTransform transform] forKey:@"inputTransform"];
    [clamp setValue:self forKey:@"inputImage"];
    return [clamp valueForKey:@"outputImage"];
}

затем размыть, а затем обрезать до исходного экстента. Таким образом, вы получите непрозрачные края.


решение@BBC_Z является правильным.

хотя я считаю более элегантным обрезать не в соответствии с видом, а с изображением.
И вы можете отрезать бесполезные размытые края:

// Crop transparent edges from blur
resultImage = [resultImage imageByCroppingToRect:(CGRect){
    .origin.x = blurRadius,
    .origin.y = blurRadius,
    .size.width = originalCIImage.extent.size.width - blurRadius*2,
    .size.height = originalCIImage.extent.size.height - blurRadius*2
}];