如何创建一个适用于Retina显示的CGBitmapContext,而不是浪费空间进行常规显示?

nop*_*ole 15 core-graphics cgbitmapcontextcreate ios retina-display

是否真的如果它在UIKit,包括drawRect,Retina显示器的高清方面是自动处理?那么这意味着drawRect,1024 x 768视图的当前图形上下文实际上是2048 x 1536像素的位图上下文?

(更新:如果我使用当前上下文创建图像drawRect并打印其大小:

CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef image = CGBitmapContextCreateImage(context);
NSLog(@"width of context %i", (int) CGImageGetWidth(image));
NSLog(@"height of context %i", (int) CGImageGetHeight(image));
Run Code Online (Sandbox Code Playgroud)

然后在新的iPad上,状态栏被禁用,打印2048和1536,iPad 2将显示1024和768)

我们实际上享受为我们自动处理1点= 4像素的奢侈品.

但是,如果我们使用CGBitmapContextCreate,那么那些将是像素,而不是点?(至少如果我们为该位图提供数据缓冲区,缓冲区的大小(字节数)显然不是用于更高的分辨率,而是用于标准分辨率,即使我们NULL作为缓冲区传递以便CGBitmapContextCreate为我们处理缓冲区,大小可能与传入数据缓冲区相同,而且只是标准分辨率,而不是Retina的分辨率.

我们总是可以为iPad 1和iPad 2以及新iPad创建2048 x 1536,但它会浪费内存,处理器和GPU功能,因为它只需要新iPad.

那么我们是否必须使用a if () { } else { }来创建这样的位图上下文,我们如何实际这样做呢?并且我们所有的代码CGContextMoveToPoint都必须针对Retina显示器进行调整才能使用x * 2,y * 2而非视网膜显示器也只需使用x, y?这对代码来说可能非常混乱.(或者我们可以定义一个局部变量scaleFactor,并设置它[[UIScreen mainScreen] scale]所以它是1标准分辨率和2如果是视网膜,所以我们xy总是会x * scaleFactor,y * scaleFactor而不是只xy当我们绘制使用CGContextMoveToPoint等)

UIGraphicsBeginImageContextWithOptions如果传入0.0的比例,似乎可以自动为Retina创建一个,但是如果我需要创建上下文并保留它(并使用ivar或UIViewController的属性来保存它),我认为不能使用它. .如果我不使用它UIGraphicsEndImageContext,它会停留在图形上下文堆栈中,所以我似乎必须使用它CGBitmapContextCreate.(或者我们只是让它留在堆栈的底部而不用担心它?)

nop*_*ole 40

经过更多的研究,我找到了以下解决方案:

如果必须使用CGBitmapContextCreate,则有两个步骤可以使上下文的大小和坐标系统适合标准显示或Retina显示:

float scaleFactor = [[UIScreen mainScreen] scale];

CGSize size = CGSizeMake(768, 768);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef context = CGBitmapContextCreate(NULL, 
                           size.width * scaleFactor, size.height * scaleFactor, 
                           8, size.width * scaleFactor * 4, colorSpace, 
                           kCGImageAlphaPremultipliedFirst);

CGContextScaleCTM(context, scaleFactor, scaleFactor);
Run Code Online (Sandbox Code Playgroud)

样本是创建一个768 x 768 区域,而在新iPad上,它将是1536 x 1536 像素.在iPad 2上,它是768 x 768 像素.

一个关键因素是,CGContextScaleCTM(context, scaleFactor, scaleFactor);用于调整坐标系,因此CGContextMoveToPoint无论是标准分辨率还是Retina分辨率,Core Graphics的任何绘图(如等)都将自动工作.


还有一点需要注意的是,UIGraphicsBeginImageContext(CGSizeMake(300, 300));它将在Retina显示屏上创建一个300 x 300 像素,同时在Retina显示屏上UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, 0.0);创建600 x 600 像素.的0.0是用于在方法调用来自动得到适当的大小以便显示标准或视网膜显示.