How to create a CGBitmapContext which works for Retina display and not wasting space for regular display?
cgbitmapcontextcreate, core-graphics, ios, retina-display
Solution
After doing more research, I found the following solution:
If you have to use `CGBitmapContextCreate`, then there are two steps that can make the context with a size and coordinate system tailored to a standard display or Retina display:
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);
The sample is to create a 768 x 768 point region, and on The New iPad, it will be 1536 x 1536 pixel. On iPad 2, it is 768 x 768 pixel.
A key factor is that, `CGContextScaleCTM(context, scaleFactor, scaleFactor);` is used to adjust the coordinate system, so that any drawing by Core Graphics, such as `CGContextMoveToPoint`, etc, will automatically work, no matter it is standard resolution or the Retina resolution.
One more note is that `UIGraphicsBeginImageContext(CGSizeMake(300, 300));` will create a 300 x 300 pixel on Retina display, while `UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, 0.0);` will create 600 x 600 pixel on the Retina display. The `0.0` is for the method call to automatically give the proper size for standard display or Retina display.
Problem
Is it true that if it is in UIKit, including `drawRect`, the HD aspect of Retina display is automatically handled? So does that mean in `drawRect`, the current graphics context for a 1024 x 768 view is actually a 2048 x 1536 pixel Bitmap context? (Update: if I create an image using the current context in `drawRect` and print its size: ``` CGContextRef context = UIGraphicsGetCurrentContext(); CGImageRef image = CGBitmapContextCreateImage(context); NSLog(@"width of context %i", (int) CGImageGetWidth(image)); NSLog(@"height of context %i", (int) CGImageGetHeight(image)); ``` then on the new iPad, with the status bar disabled, 2048 and 1536 is printed, and iPad 2 will show 1024 and 768) We actually enjoy the luxury of 1 point = 4 pixels automatically handled for us. However, if we use `CGBitmapContextCreate`, then those will really be pixels, not points? (at least if we provide a data buffer for that bitmap, the size of the buffer (number of bytes) is obviously not for higher resolution, but for standard resolution, and even if we pass `NULL` as the buffer so that `CGBitmapContextCreate` handles the buffer for us, the size probably is the same as if we pass in a data buffer, and it is just standard resolution, not Retina's resolution). We can always create 2048 x 1536 for iPad 1 and iPad 2 as well as the New iPad, but it will waste memory and processor and GPU power, as it is only needed for the New iPad. So do we have to use a `if () { } else { }` to create such a bitmap context and how do we actually do so? And all our code `CGContextMoveToPoint` has to be adjusted for Retina display to use `x * 2` and `y * 2` vs non-retina display of just using `x, y` as well? That can be quite messy for the code. (or maybe we can define a local variable `scaleFactor` and set it to `[[UIScreen mainScreen] scale]` so it is 1 for standard resolution and 2 if it is retina, so our `x` and `y` will always be `x * scaleFactor`, `y * scaleFactor` instead of just `x` and `y` when we draw using `CGContextMoveToPoint`, etc.) It seems that `UIGraphicsBeginImageContextWithOptions` can create one for Retina automatically if the scale of 0.0 is passed in, but I don't think it can be used if I need to create the context and keep it (and using ivar or property of UIViewController to hold it). If I don't release it using `UIGraphicsEndImageContext`, then it stays in the graphics context stack, so it seems like I have to use `CGBitmapContextCreate` instead. (or do we just let it stay at the bottom of the stack and not worry about it?)