xcode CGContext 和视网膜显示

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8545547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:46:33  来源:igfitidea点击:

CGContext and retina display

iphonexcode

提问by werbary

guys, this is my code:

伙计们,这是我的代码:

- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx {
    //background
    CGContextSetFillColorWithColor(ctx, [[UIColor colorWithRed:((float)238 / 255.0f) green:((float)233 / 255.0f) blue:((float)215 / 255.0f) alpha:1] CGColor]);
    CGContextFillRect(ctx, CGRectInset(leavesView.bounds, 0, 0));
    //text
    CGContextSetTextDrawingMode(ctx, kCGTextFill);
    CGContextSetTextMatrix(ctx, CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0));
    CGContextSetFillColorWithColor(ctx, [[UIColor blackColor] CGColor]);
    UIGraphicsPushContext(ctx);

    CGContextSaveGState(ctx);
    CGContextTranslateCTM(ctx, 0.1f, leavesView.bounds.size.height);
    CGContextScaleCTM(ctx, 1.0f, -1.0f);

    CGRect textRect = CGRectMake(5, 5, leavesView.bounds.size.width-10, leavesView.bounds.size.height-10);
    if (pages.count > 0 && pages.count-1 >= index) {
        [[pages objectAtIndex:index] drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
    }

    CGContextRestoreGState(ctx);

    UIGraphicsPopContext();
}

It works perfect on iPhone 2G, 3G, 3GS, but on new models I have problems.

它在 iPhone 2G、3G、3GS 上完美运行,但在新型号上我遇到了问题。

On the retina text is drawn not to double the resolution, as in the standard.

在视网膜上绘制的文本不会像标准那样使分辨率翻倍。

Have you any ideas?

你有什么想法吗?

回答by Olof

Try setting the layers contentScale variable like this:

尝试像这样设置图层 contentScale 变量:

layer.contentsScale = [UIScreen mainScreen].scale;

This should make the code adapt to retina/nonretina displays.

这应该使代码适应视网膜/非视网膜显示。

回答by chazzwozzer

Looks like you are using the Leavesproject on git. I had this same issue in my project and solved it as follows.

看起来您正在git上使用Leaves项目。我在我的项目中遇到了同样的问题,并按如下方式解决了它。

First, you need to size and scale the original Core Graphics context created in imageForPageIndex: in LeavesCache.m according to the devices screen scale. Make sure to also scale CGContextClipToRect as well.

首先,您需要根据设备屏幕比例调整在 LeavesCache.m 中的 imageForPageIndex: 中创建的原始 Core Graphics 上下文的大小和缩放比例。确保也缩放 CGContextClipToRect。

- (CGImageRef) imageForPageIndex:(NSUInteger)pageIndex {
    CGFloat scale = [[UIScreen mainScreen] scale];  // we need to size the graphics context according to the device scale
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, 
                                             pageSize.width*scale, 
                                             pageSize.height*scale, 
                                             8,                     /* bits per component*/
                                             pageSize.width*scale * 4,  /* bytes per row */
                                             colorSpace, 
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGColorSpaceRelease(colorSpace);
    CGContextClipToRect(context, CGRectMake(0, 0, pageSize.width*scale, pageSize.height*scale));

    CGContextScaleCTM(context, scale, scale);

    [dataSource renderPageAtIndex:pageIndex inContext:context];

    CGImageRef image = CGBitmapContextCreateImage(context);
    CGContextRelease(context);

    [UIImage imageWithCGImage:image];
    CGImageRelease(image);

    return image;
}

Next, in setUpLayers in LeavesView.m, you'll need to apply the device screen scale to each CALayer that gets initialized. As posted by Brad Larson in a similar question:

接下来,在 LeavesView.m 的 setUpLayers 中,您需要将设备屏幕比例应用于每个初始化的 CALayer。正如布拉德·拉森 (Brad Larson) 在类似问题中发表的那样

By default, your CALayer is not rendering its Quartz content at the higher resolution of the Retina display screen. You can enable this using code like the following:

默认情况下,您的 CALayer 不会以更高分辨率的 Retina 显示屏呈现其 Quartz 内容。您可以使用如下代码启用此功能:

layer.contentsScale = [[UIScreen mainScreen] scale];

So here are the first few lines from setUpLayers in LeavesView.m where I apply the device scale to the topPage CALayer. You'll need to do this to all CALayers and CAGradientLayers initialized in setUpLayers:

所以这里是 LeavesView.m 中 setUpLayers 的前几行,我将设备比例应用于 topPage CALayer。您需要对在 setUpLayers 中初始化的所有 CALayers 和 CAGradientLayers 执行此操作:

- (void) setUpLayers {
    // Set the backgound image of the leave view to the book page
    UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"open_book_page_turn.png"]];

    self.clipsToBounds = YES;

    topPage = [[CALayer alloc] init];
    topPage.contentsScale = [[UIScreen mainScreen] scale];  // We need to apply the device display scale to each layer
    topPage.masksToBounds = YES;
    topPage.contentsGravity = kCAGravityLeft;
    topPage.backgroundColor = [[UIColor whiteColor] CGColor];
    topPage.backgroundColor = [background CGColor];

    ...

}

回答by Saren Inden

You can just set the scale when you start the context

您可以在启动上下文时设置比例

+ (UIImage *)imageWithView:(UIView *)view {
    UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, [[UIScreen mainScreen] scale]);

    [[view layer] renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return result;
}

回答by technerd

For Swift 3

对于Swift 3

func getImageFromContext() -> UIImage{

    UIGraphicsBeginImageContextWithOptions(self.frame.size, false, UIScreen.main.scale)
    self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
    self.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image!
}