【问题标题】:CGContext and retina displayCGContext 和视网膜显示
【发布时间】:2011-12-17 14:57:27
【问题描述】:

伙计们, 这是我的代码:

- (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();
}

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

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

你有什么想法吗?

【问题讨论】:

    标签: iphone xcode


    【解决方案1】:

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

    layer.contentsScale = [UIScreen mainScreen].scale;
    

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

    【讨论】:

    • 我已经对 CALayer 进行了子类化,我必须在 init 方法中执行此操作。在 drawWithContext 方法中它抛出了一个只读错误。
    【解决方案2】:

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

    首先,您需要根据设备的屏幕比例,对在 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;
    }
    

    接下来,在 LeavesView.m 的 setUpLayers 中,您需要将设备屏幕比例应用于每个初始化的 CALayer。正如布拉德·拉尔森在similar question 中发布的那样:

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

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

    这里是 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];
    
        ...
    
    }
    

    【讨论】:

    • topPage.contentsScale = [[UIScreen mainScreen] scale];没有帮助,看起来仍然像素化......
    【解决方案3】:

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

    + (UIImage *)imageWithView:(UIView *)view {
        UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, [[UIScreen mainScreen] scale]);
    
        [[view layer] renderInContext:UIGraphicsGetCurrentContext()];
    
        UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    
        UIGraphicsEndImageContext();
    
        return result;
    }
    

    【讨论】:

      【解决方案4】:

      对于 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!
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-31
        相关资源
        最近更新 更多