用于视网膜显示的 CoreGraphics

Posted

技术标签:

【中文标题】用于视网膜显示的 CoreGraphics【英文标题】:CoreGraphics for retina display 【发布时间】:2011-01-16 19:13:38 【问题描述】:

我正在使用以下代码对我加载的图像执行一些操作,但我发现当它在视网膜显示器上时显示变得模糊

- (UIImage*)createImageSection:(UIImage*)image section:(CGRect)section


float originalWidth = image.size.width ;
float originalHeight = image.size.height ;
int w = originalWidth * section.size.width;
int h = originalHeight * section.size.height;

CGContextRef ctx = CGBitmapContextCreate(nil, w, h, 8, w * 8,CGImageGetColorSpace([image CGImage]), kCGImageAlphaPremultipliedLast);
CGContextClearRect(ctx, CGRectMake(0, 0, originalWidth * section.size.width, originalHeight * section.size.height)); // w + h before
CGContextTranslateCTM(ctx, (float)-originalWidth * section.origin.x, (float)-originalHeight * section.origin.y);
CGContextDrawImage(ctx, CGRectMake(0, 0, originalWidth, originalHeight), [image CGImage]);
CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
UIImage* resultImage = [[UIImage alloc] initWithCGImage:cgImage];

CGContextRelease(ctx);
CGImageRelease(cgImage);

return resultImage;

如何更改它以使其与视网膜兼容。

提前感谢您的帮助

最好, DV

【问题讨论】:

【参考方案1】:

CGImages 不考虑您设备的 Retina-ness,因此您必须自己这样做。

为此,您需要将 CoreGraphics 例程中使用的所有坐标和大小乘以输入图像的 scale 属性(在 Retina 设备上为 2.0),以确保以双倍分辨率进行所有操作.

然后你需要将resultImage的初始化更改为使用initWithCGImage:scale:orientation:并输入相同的比例因子。这就是 Retina 设备以原始分辨率而不是像素加倍分辨率呈现输出的原因。

【讨论】:

如果您通过调用 CGContextScaleCTM(UIGraphicsGetCurrentContext(), 2, 2) 更改上下文的 CTM(当前变换矩阵),则无需手动乘以坐标,您可以像使用非视网膜图像。 抱歉,评论太快了,编辑太晚了。如果你这样做,你不需要考虑自己缩放所有坐标:CGFloat scale = [[UIScreen mainScreen] scale]; CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale); 是的。很好的解决方案。 如果您只在该图像内绘制一部分(子矩形),仍然必须手动修复比例。【参考方案2】:

感谢您的回答,帮助了我!无论如何,为了更清楚,OP的代码应该这样更改:

- (UIImage*)createImageSection:(UIImage*)image section:(CGRect)section        

    CGFloat scale = [[UIScreen mainScreen] scale]; ////// ADD

    float originalWidth = image.size.width ;
    float originalHeight = image.size.height ;
    int w = originalWidth * section.size.width *scale; ////// CHANGE
    int h = originalHeight * section.size.height *scale; ////// CHANGE

    CGContextRef ctx = CGBitmapContextCreate(nil, w, h, 8, w * 8,CGImageGetColorSpace([image CGImage]), kCGImageAlphaPremultipliedLast);
    CGContextClearRect(ctx, CGRectMake(0, 0, originalWidth * section.size.width, originalHeight * section.size.height)); // w + h before
    CGContextTranslateCTM(ctx, (float)-originalWidth * section.origin.x, (float)-originalHeight * section.origin.y);

    CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale); ////// ADD

    CGContextDrawImage(ctx, CGRectMake(0, 0, originalWidth, originalHeight), [image CGImage]);
    CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
    UIImage* resultImage = [[UIImage alloc] initWithCGImage:cgImage];

    CGContextRelease(ctx);
    CGImageRelease(cgImage);

    return resultImage;

【讨论】:

【参考方案3】:

斯威夫特版本:

    let scale = UIScreen.mainScreen().scale

    CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)

【讨论】:

以上是关于用于视网膜显示的 CoreGraphics的主要内容,如果未能解决你的问题,请参考以下文章

为视网膜显示调整图像大小

视网膜显示器兼容性

视网膜显示屏,高分辨率背景图像

在 iPhone SDK 中检测视网膜屏幕/iPhone 4

iOS UI 自定义按钮图片

d3:结合canvas + svg用于视网膜