hoc*_*man 27 macos objective-c core-image
正如我注意到当CIGaussianBlur应用于图像时,图像的角落变得模糊,因此它看起来比原始的小.所以我发现我需要正确裁剪它以避免图像的透明边缘.但是如何计算我需要根据模糊量裁剪多少?
例:
原始图片:

图像有50 inputRadius的CIGaussianBlur(蓝色是一切的背景):

Eri*_*ary 52
以下面的代码为例......
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *inputImage = [[CIImage alloc] initWithImage:image];
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:inputImage forKey:kCIInputImageKey];
[filter setValue:[NSNumber numberWithFloat:5.0f] forKey:@"inputRadius"];
CIImage *result = [filter valueForKey:kCIOutputImageKey];
CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
Run Code Online (Sandbox Code Playgroud)
这会生成您在上面提供的图像.但是,如果我改为使用原始图像rect来创建上下文中的CGImage,则生成的图像是所需的大小.
CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];Run Code Online (Sandbox Code Playgroud)
Mac*_*ser 24
有两个问题.第一个是模糊滤镜对输入图像边缘之外的像素进行采样.这些像素是透明的.这就是透明像素的来源.诀窍是在应用模糊滤镜之前扩展边缘.这可以通过钳位滤波器完成,例如:
CIFilter *affineClampFilter = [CIFilter filterWithName:@"CIAffineClamp"];
CGAffineTransform xform = CGAffineTransformMakeScale(1.0, 1.0);
[affineClampFilter setValue:[NSValue valueWithBytes:&xform
objCType:@encode(CGAffineTransform)]
forKey:@"inputTransform"];
Run Code Online (Sandbox Code Playgroud)
此滤镜无限延伸边缘并消除透明度.下一步是应用模糊滤镜.
第二个问题有点奇怪.一些渲染器为模糊滤镜生成更大的输出图像,您必须通过某种偏移调整生成的CIImage的原点,例如:
CGImageRef cgImage = [context createCGImage:outputImage
fromRect:CGRectOffset([inputImage extend],
offset, offset)];
Run Code Online (Sandbox Code Playgroud)
我的iPhone上的软件渲染器需要三倍的模糊半径作为偏移.同一iPhone上的硬件渲染器根本不需要任何偏移.也许你可以从输入和输出图像的大小差异中推断出偏移,但我没有尝试......
orj*_*orj 13
要获得具有硬边的图像的漂亮模糊版本,首先需要将CIAffineClamp应用于源图像,将其边缘扩展,然后您需要确保在生成输出图像时使用输入图像的范围.
代码如下:
CIContext *context = [CIContext contextWithOptions:nil];
UIImage *image = [UIImage imageNamed:@"Flower"];
CIImage *inputImage = [[CIImage alloc] initWithImage:image];
CIFilter *clampFilter = [CIFilter filterWithName:@"CIAffineClamp"];
[clampFilter setDefaults];
[clampFilter setValue:inputImage forKey:kCIInputImageKey];
CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setValue:clampFilter.outputImage forKey:kCIInputImageKey];
[blurFilter setValue:@10.0f forKey:@"inputRadius"];
CIImage *result = [blurFilter valueForKey:kCIOutputImageKey];
CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];
UIImage result = [[UIImage alloc] initWithCGImage:cgImage scale:image.scale orientation:UIImageOrientationUp];
CGImageRelease(cgImage);
Run Code Online (Sandbox Code Playgroud)
请注意,此代码已在iOS上测试过.对于OS X应该是类似的(用NSImage代替UIImage).
我看到了一些解决方案,并想根据这里分享的一些想法推荐一个更现代的解决方案:
private lazy var coreImageContext = CIContext() // Re-use this.
func blurredImage(image: CIImage, radius: CGFloat) -> CGImage? {
let blurredImage = image
.clampedToExtent()
.applyingFilter(
"CIGaussianBlur",
parameters: [
kCIInputRadiusKey: radius,
]
)
.cropped(to: image.extent)
return coreImageContext.createCGImage(blurredImage, from: blurredImage.extent)
}
Run Code Online (Sandbox Code Playgroud)
如果你需要UIImage之后,你当然可以像这样得到它:
let image = UIImage(cgImage: cgImage)
Run Code Online (Sandbox Code Playgroud)
...对于那些想知道的人,返回 a 的原因CGImage是(如Apple 文档中所述):
由于 Core Image 的坐标系统与 不匹配
UIKit,这种过滤方法在UIImageView以“contentMode”显示时可能会产生意想不到的结果。确保用 a 支持它,CGImage以便它正确处理 contentMode。
如果你需要一个CIImage你可以返回它,但在这种情况下,如果你正在显示图像,你可能需要小心。
这对我有用:)
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *inputImage = [[CIImage alloc] initWithImage:image];
CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setDefaults];
[blurFilter setValue:inputImage forKey:@"inputImage"];
CGFloat blurLevel = 20.0f; // Set blur level
[blurFilter setValue:[NSNumber numberWithFloat:blurLevel] forKey:@"inputRadius"]; // set value for blur level
CIImage *outputImage = [blurFilter valueForKey:@"outputImage"];
CGRect rect = inputImage.extent; // Create Rect
rect.origin.x += blurLevel; // and set custom params
rect.origin.y += blurLevel; //
rect.size.height -= blurLevel*2.0f; //
rect.size.width -= blurLevel*2.0f; //
CGImageRef cgImage = [context createCGImage:outputImage fromRect:rect]; // Then apply new rect
imageView.image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14616 次 |
| 最近记录: |