2

プログラムCALayerで、ピクセルノイズを少し適用するサブクラスを作成しています。このコードは、レイヤーにノイズをレンダリングするという点で機能しますが、画像に奇妙なアーティファクトがあり、根本的な原因を特定できません。

noiseOpacityこれは、問題をより目立たせるために上に向けたサンプル画像です。

ここに画像の説明を入力してください

ピンクのボックスは、次のビットを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);
}

基本的に、フィルターへの入力としてCIImageを使用してinitを作成します。次に、それを描画するときに、(範囲は常にまたは0)を使用してそれを作成し、コンテキストに描画します。CIRandomGeneratorCIColorMonochromeCGImageRefself.bounds infinite

結果はほとんど問題ありませんが、画像でわかるように、ストレッチが行われているようです。ここで何が起きてるの?

4

1 に答える 1

8

元の問題を修正していませんが、私は別の角度からこれにアプローチし、出力を複製しました。のサイズの単一の画像を生成しようとする代わりに、self.bounds64x64のみの画像を生成し、を使用してタイリングしていCGContextDrawTiledImageます。現在、固定サイズでサイズ設定しているため、drawInContext:メソッドからコードを引き出すことができます。そして最後に、drawメソッドで行われる画像生成がなくなったため、静的変数にすることができたので、一度だけ生成されます。完全なクラスは次のとおりです。

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

iOS 6(またはそれ以降)CIColorMonochromeCIRandomGenerator必要です。必要なフレームワーク(および)を必ず含めてください。CoreImage.frameworkQuartzCore.framework

于 2012-07-04T21:43:57.207 に答える