Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you generate an RGBA image in Core Graphics?

I'm trying to generate an RGBA8 image from text to use as an OpenGL ES 2.0 texture.

+(UIImage *)imageFromText:(NSString *)text
{
  UIFont *font = [UIFont systemFontOfSize:20.0];  
  CGSize size  = [text sizeWithFont:font];

  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef contextRef =  CGBitmapContextCreate (NULL,
                                                    size.width, size.height,
                                                    8, 4*size.width,
                                                    colorSpace,
                                                    kCGImageAlphaLast
                                                    );
  CGColorSpaceRelease(colorSpace);
  UIGraphicsPushContext(contextRef);

  [text drawAtPoint:CGPointMake(0.0, 0.0) withFont:font];
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

  UIGraphicsPopContext();

  return image;
}

Unfortunately, there's no CGColorSpaceCreateDeviceRGBA, and CGColorSpaceCreateDeviceRGB results in the following error:

CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaLast; 448 bytes/row.

What am I missing to create the proper RGBA8 format that OpenGL wants here?

Update: I changed the last parameter of CGBitmapContextCreate from kCGImageAlphaNone (which it was when I copy pasted the code) to kCGImageAlphaLast, which is one of several variations I've tried in error.

Update 2: UIGraphicsGetImageFromCurrentImageContext() returns nil if the context was not created with UIGraphicsBeginImageContext(), so it is necessary to extract the image differently: [UIImage imageWithCGImage:CGBitmapContextCreateImage(contextRef)].

like image 202
Ian Terrell Avatar asked Jul 28 '11 15:07

Ian Terrell


2 Answers

The color space you specify during creation wouldn't cause an error like that.

The reason you're getting that error is that you've specified 8 bits per component, presumably 4 color components in the 4*size.width value you passed in for bytesPerRow, yet a bitmapInfo parameter of kCGImageAlphaNone. kCGImageAlphaNone means only RGB, not RGBA. If you want RGBA, you should most likely specify kCGImageAlphaLast kCGImageAlphaPremultipliedLast.

[EDIT] sorry. I should have said kCGImageAlphaPremultipliedLast, not kCGImageAlphaLast.

So, something like this:

CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef contextRef =  CGBitmapContextCreate(NULL,
                                                 size.width,
                                                 size.height,
                                                 8,
                                                 4 * size.width,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast);
like image 176
NSGod Avatar answered Sep 27 '22 21:09

NSGod


I was getting the same unsupported parameter combination error even though I was using kCGImageAlphaPremultipliedLast. The issue in my case turned out to be that the width I was getting was fractional. Turning it into an integer by passing int(width) to CGBitmapContextCreate solved the problem.

--Edit in response to Steven's comment--

The issue with feeding in a fractional width as the second argument is not that CGBitmapContextCreate interprets it as such -- as stated, it gets casted implicitly to the argument's unsigned integer type. Rather, it produces a discrepancy in the bytes_per_row argument, since int(width * 4) is not the same as int(width) * 4. E.g. if the width is 22.5, then width gets truncated to 22, but width * 4 computes to 90, not 88.

like image 45
er0 Avatar answered Sep 27 '22 22:09

er0