gpt4 book ai didi

ios - 使用 Core Image 渲染随机噪声 CALayer 会生成奇怪的伪像

转载 作者:行者123 更新时间:2023-12-01 17:27:06 25 4
gpt4 key购买 nike

我正在以编程方式创建一个 CALayer 子类,它向自身应用了一些像素噪声。该代码的工作原理是它在层中渲染噪声,但图像上有一个我无法确定根本原因的奇怪伪像。

这里是一个示例图像,其中 noiseOpacity 出现以使问题更加明显。

enter image description here

粉红色框是一个 UANoisyGradientLayer,一个 CAGradientLayer 子类,具有以下位:

@interface UANoisyGradientLayer ()
@property (nonatomic, retain) CIContext *noiseContext;
@property (nonatomic, retain) CIFilter *noiseGenerator;
@property (nonatomic, retain) CIImage *noiseImage;
@end

@implementation UANoisyGradientLayer

@synthesize noiseOpacity = _noiseOpacity, noiseImage;

- (id)init {
self = [super init];
if (self) {
self.noiseOpacity = 0.10;
self.noiseContext = [CIContext contextWithOptions:nil];
self.noiseGenerator = [CIFilter filterWithName:@"CIColorMonochrome"];
[self.noiseGenerator setValue:[[CIFilter filterWithName:@"CIRandomGenerator"] valueForKey:@"outputImage"] forKey:@"inputImage"];
[self.noiseGenerator setDefaults];

self.noiseImage = [self.noiseGenerator outputImage];

}
return self;
}

- (void)drawInContext:(CGContextRef)ctx {

[super drawInContext:ctx];

CGRect extentRect = [self.noiseImage extent];
if (CGRectIsInfinite(extentRect) || CGRectIsEmpty(extentRect)) {
extentRect = self.bounds;
}

CGImageRef cgimg = [self.noiseContext createCGImage:self.noiseImage fromRect:extentRect];
CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
CGContextSetAlpha(ctx, self.noiseOpacity);
CGContextDrawImage(ctx, self.bounds, cgimg);
CGImageRelease(cgimg);
}

基本上,我使用 CIRandomGenerator 作为 CIColorMonochrome 过滤器的输入在 init 中创建了 CIImage。然后,当需要绘制它时,我使用 self.bounds 从中创建一个 CGImageRef(范围是 always infinite 或 0),并将其绘制到上下文中。

结果基本没问题,但正如您在图片中看到的,似乎有一些拉伸(stretch)。这里发生了什么?

最佳答案

虽然没有解决原始问题,但我从不同的角度解决了这个问题并复制了输出。我现在没有尝试生成大小为 self.bounds 的单个图像,而是生成一个只有 64x64 的图像,然后使用 CGContextDrawTiledImage 对其进行平铺。因为我现在以固定大小调整它的大小,所以我可以从 drawInContext: 方法中提取一些代码。最后,因为绘制方法中不再生成图像,所以我能够将其设为静态变量,因此它只生成一次!这是完整的类(class):

static CGImageRef   __noiseImage        = nil;
static CGFloat __noiseImageWidth = 0.0;
static CGFloat __noiseImageHeight = 0.0;

@implementation UANoisyGradientLayer

@synthesize noiseOpacity = _noiseOpacity;

- (id)init {
self = [super init];
if (self) {
self.noiseOpacity = 0.1f;
self.needsDisplayOnBoundsChange = YES;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CIContext *noiseContext = [CIContext contextWithOptions:nil];

CIFilter *noiseGenerator = [CIFilter filterWithName:@"CIColorMonochrome"];
[noiseGenerator setValue:[[CIFilter filterWithName:@"CIRandomGenerator"] valueForKey:@"outputImage"] forKey:@"inputImage"];
[noiseGenerator setDefaults];

CIImage *ciImage = [noiseGenerator outputImage];

CGRect extentRect = [ciImage extent];
if (CGRectIsInfinite(extentRect) || CGRectIsEmpty(extentRect)) {
extentRect = CGRectMake(0, 0, 64, 64);
}

__noiseImage = [noiseContext createCGImage:ciImage fromRect:extentRect];
__noiseImageWidth = CGImageGetWidth(__noiseImage);
__noiseImageHeight = CGImageGetHeight(__noiseImage);
});
}

return self;
}

- (void)drawInContext:(CGContextRef)ctx {

[super drawInContext:ctx];

if (self.noiseOpacity > 0) {

CGContextSaveGState(ctx);
CGPathRef path = [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.cornerRadius] CGPath];
CGContextAddPath(ctx, path);
CGContextClip(ctx);
CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
CGContextSetAlpha(ctx, self.noiseOpacity);


CGContextDrawTiledImage(ctx, CGRectMake(0, 0, __noiseImageWidth, __noiseImageHeight), __noiseImage);

CGContextRestoreGState(ctx);
}
}

@end

注意:CIColorMonochromeCIRandomGenerator 需要iOS 6(或更新版本)。确保包含所需的框架(CoreImage.frameworkQuartzCore.framework)。

关于ios - 使用 Core Image 渲染随机噪声 CALayer 会生成奇怪的伪像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11333965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com