CIFilter guassianBlur和boxBlur正在缩小图像 - 如何避免调整大小?

fou*_*dry 8 macos xcode cocoa objective-c core-image

我正在拍摄a的内容的快照NSView,应用a CIFilter,并将结果放回到视图中.如果CIFilter是模糊的形式,例如CIBoxBlurCIGuassianBlur,则过滤后的结果略小于原始模糊.当我迭代地这样做时,结果变得越来越小,我想避免.

这里提到的问题虽然略有不同(Quartz Composer).苹果FunHouse演示应用程序适用于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];
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用颜色变化滤镜,例如CISepiaTone不会移动像素,则不会发生收缩.

我想知道是否有一个不涉及潜入的快速修复openGL

小智 16

它们实际上并没有缩小图像,它们正在扩展它(我认为所有边缘都有7个像素)和默认的UIView'缩放到视图'使它看起来像是缩小了.

剪裁你的CIImage:

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

其中view是你所引入的NSView的原始边界,'scale'是你的[UIScreen mainScreen]比例].

  • 在我看来,更简单的方法是做:`CGImageRef cgImage = [context createCGImage:result fromRect:[**ciImage**extent]];`所以范围来自原始图像而不是输出过滤器. (3认同)

小智 14

您可能希望在使用模糊之前夹住图像:

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

然后模糊,然后裁剪到原始范围.你会以这种方式获得不透明的边缘.


NSA*_*ict 5

@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
}];
Run Code Online (Sandbox Code Playgroud)