CGContextDrawImage 画大图很模糊

Posted

技术标签:

【中文标题】CGContextDrawImage 画大图很模糊【英文标题】:CGContextDrawImage draws large images very blurry 【发布时间】:2013-12-11 02:04:34 【问题描述】:

我正在尝试使用 CGContextDrawImage(...) 制作一个可以绘制大型(例如 2048 x 1537)图像的一部分的对象。它工作得很好,只是它非常模糊。我正在使用覆盖 drawLayer:inContext: 像这样的“drawingController”

-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
    CGImageRef drawImage = CGImageRetain(imageToDraw);
    if(drawImage) 
        CGRect drawRect = CGRectMake(0, 0, 1024, 748);//Just hard coded to my window size for now.
        CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
        CGContextDrawImage(ctx, drawRect, drawImage);
    
    CGImageRelease(drawImage);

这就是我设置自定义图像托管视图的方式:

- (id)initWithFrame:(NSRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        // Initialization code here.
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"large" ofType:@"jpg"];
        CGImageRef imageRef = [self createCGImageFromFilePath:filePath];


        drawingController = [[DrawingLayerController alloc] init];
        drawingController.imageToDraw = imageRef;

        [self setWantsLayer:YES];
        imageLayer = [[CALayer alloc] init];
        imageLayer.frame = self.bounds;
        imageLayer.drawsAsynchronously = YES;
        imageLayer.delegate = drawingController;
        [self.layer addSublayer:imageLayer];

        imageLayer.contentsRect = CGRectMake(0.5, 0.265452179, 0.5, 0.486662329); //Just an example contents rect.
        imageLayer.drawsAsynchronously = YES;

        [imageLayer setNeedsDisplay];
        [imageLayer displayIfNeeded];
    
    return self;

这是在预览中打开的以类似缩放比例在源图像旁边生成的图像的一部分,因此您可以看到与源图像相比图像的模糊程度。

如您所见,我的代码生成的图像看起来很糟糕。这是怎么回事?

另外,为了完整起见,我尝试将 CATiledLayer 用于我的 imageLayer。生成的图像看起来同样糟糕。

最后一点:代码需要与 ios 和 OSX 兼容,但我正在 OSX 上进行所有测试。

编辑:感谢@Andrea,我在 CGContextDrawImage(...) 上面添加了以下内容

CGFloat scale = MAX(1,MAX(CGImageGetWidth(drawImage)/drawRect.size.width,CGImageGetHeight(drawImage)/drawRect.size.height));

layer.contentsScale = scale;

【问题讨论】:

请尝试将 CALayer.contentsScale 设置为 [UIScreen mainScreen].scale @yurish:UIScreen 在 OS X 上不可用。 【参考方案1】:

我对 osx 不太了解,但我可以给你一些建议。

检查评论中所述的contentScale 属性,我还写了一个question 关于它,但我从来没有真正的答案 大部分时间模糊是由于不匹配的像素,这要求系统对图像应用抗锯齿,我看到你设置了contentsRect 这个,用contentsGravity,可能会改变比例和缩放图像把它变成模糊的。这是一个很好的answer。 你的 contentGravity 是什么? 第一次尝试保持简单,你真的需要异步绘制吗?

希望这会有所帮助。

【讨论】:

contentScale 为 2.0 确实会使图像变得更清晰。我完全不知道如何解释这一点。为什么我需要使用 2.0 的内容量表?我将图像直接从文件加载到 CGImageRef 中,因此没有 NSImage @2x 魔术发生,我正在绘制到非视网膜屏幕。 嗨@RagnarDanneskjöld 原始图像的分辨率是多少? 嗨@RagnarDanneskjöld 图像的分辨率更大(两倍),因此图层需要在更小的空间内重新绘制它,所以可能您需要在绘制时设置一些选项,您是否尝试过CGContextSetShouldAntialias(ctx, true); CGContextSetAllowsAntialiasing(ctx, true);。我有一个类似的问题,并通过直接在图层上将 minificationFilter 设置为 kCAFilterTrilinear 来解决,但我直接将图像设置为图层的内容 图像分辨率为 2048 x 1537。“图像的分辨率更大”——大于什么,我的图层?我不跟。该图像比我的图层的 2 倍要好得多,但是将内容比例设置为 2 会使图像与将其设置为 5 一样清晰(据我所知)。此外,抗锯齿的东西没有效果。 CGRect drawRect = CGRectMake(0, 0, 1024, 748);

以上是关于CGContextDrawImage 画大图很模糊的主要内容,如果未能解决你的问题,请参考以下文章

「技术人生」第8篇:如何画业务大图

加载图片优化(先用一张小图片做高斯模糊, 再加载大图)

c#winform编程中 在窗体上画一个大图盖住一个小图 怎么用程序实现选中小图

java如何在大图中寻找小图,并且能模糊匹配

巨大的内存峰值 - CGContextDrawImage

typora变模糊怎么回事