(更新:如果我使用drawRect中的当前上下文创建一个图像并打印其大小:
CGContextRef context = UIGraphicsGetCurrentContext(); CGImageRef image = CGBitmapContextCreateImage(context); NSLog(@"width of context %i",(int) CGImageGetWidth(image)); NSLog(@"height of context %i",(int) CGImageGetHeight(image));
然后在新的iPad上,禁用状态栏,打印2048和1536,iPad 2将显示1024和768)
我们实际上享受为我们自动处理的1点= 4像素的豪华.
但是,如果我们使用CGBitmapContextCreate,那么那些将是像素,而不是点? (至少如果我们为该位图提供一个数据缓冲区,缓冲区的大小(字节数)显然不是为了更高的分辨率,而是标准分辨率,即使我们传递NULL作为缓冲区,以便CGBitmapContextCreate处理缓冲区对于我们来说,大小可能与传入数据缓冲区一样,它只是标准分辨率,而不是Retina的分辨率).
我们可以随时为iPad 1和iPad 2以及新iPad创建2048 x 1536,但会浪费内存和处理器以及GPU的功耗,因为它只适用于New iPad.
那么我们必须使用if(){} else {}来创建这样的位图上下文,我们该如何实现呢?并且我们的所有代码CGContextMovetoPoint必须调整Retina显示以使用x * 2和y * 2与非视网膜显示刚刚使用x,y?这对于代码来说可能相当凌乱. (或者我们可以定义一个局部变量scaleFactor并将其设置为[[UIScreen mainScreen] scale],因此标准分辨率为1,如果是视网膜则为2,因此我们的x和y将始终为x * scaleFactor,y * scaleFactor而不是只使用x和y,当我们绘制使用CGContextMovetoPoint等)
看来,如果传递了0.0的比例,UIGraphicsBeginImageContextWithOptions可以自动为Retina创建一个,但是如果我需要创建上下文并保留它(并且使用ivar或UIViewController的属性来保存它),我不认为它可以被使用).如果我不使用UIGraphicsEndImageContext发布它,那么它保留在图形上下文堆栈中,所以看起来像我必须使用CGBitmapContextCreate. (或者我们只是让它留在堆栈的底部,不用担心?)
解决方法
如果您必须使用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);
示例是创建一个768 x 768点区域,而在New iPad上,它将是1536 x 1536像素.在iPad 2上,它是768 x 768像素.
一个关键因素是,CGContextScaleCTM(context,scaleFactor);用于调整坐标系,使Core Graphics的任何绘图(如CGContextMovetoPoint等)自动工作,无论是标准分辨率还是Retina分辨率.
还有一点是UIGraphicsBeginImageContext(CGSizeMake(300,300));将在Retina显示器上创建一个300 x 300像素,而UIGraphicsBeginImageContextWithOptions(CGSizeMake(300,300),NO,0.0);将在Retina显示屏上创建600 x 600像素. 0.0是用于方法调用自动给出标准显示或Retina显示的适当大小.