ppaulojr
ppaulojr

Reputation: 3647

CGContextShowTextAtPoint producing non-Retina output on Retina device

I'm trying to add a text to an UIImage and I'm getting a pixelated drawing.

I have tried some other answers with no success:

My code:

-(UIImage *)addText:(UIImage *)imgV text:(NSString *)text1
{
   int w = self.frame.size.width * 2;
   int h = self.frame.size.height * 2;
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = CGBitmapContextCreate
         (NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);

   CGContextDrawImage(context, CGRectMake(0, 0, w, h), imgV.CGImage);    
   CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1);

   char* text = (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];
   CGContextSelectFont(context, "Arial", 24, kCGEncodingMacRoman);

   // Adjust text;

   CGContextSetTextDrawingMode(context, kCGTextInvisible);
   CGContextShowTextAtPoint(context, 0, 0, text, strlen(text));

   CGPoint pt = CGContextGetTextPosition(context);
   float posx = (w/2 - pt.x)/2.0;
   float posy = 54.0;    
   CGContextSetTextDrawingMode(context, kCGTextFill);
   CGContextSetRGBFillColor(context, 255, 255, 255, 1.0);

   CGContextShowTextAtPoint(context, posx, posy, text, strlen(text));

   CGImageRef imageMasked = CGBitmapContextCreateImage(context);
   CGContextRelease(context);
   CGColorSpaceRelease(colorSpace);

   return [UIImage imageWithCGImage:imageMasked];
}

example of jagged image

Upvotes: 1

Views: 975

Answers (2)

ganime
ganime

Reputation: 129

I was facing the exact same problem and posted a question last night to which no-one replied. I have combined fnf's suggested changes with Clif Viegas's answer in the following question: CGContextDrawImage draws image upside down when passed UIImage.CGImage

to come up with the solution. My addText method is slightly different from yours:

+(UIImage *)addTextToImage:(UIImage *)img text:(NSString *)text1{

int w = img.size.width;
int h = img.size.height;

CGSize size = CGSizeMake(w, h);
if (UIGraphicsBeginImageContextWithOptions != NULL) {
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
} else {
    UIGraphicsBeginImageContext(size);
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();


CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0,h);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);

CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1);

char* text = (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];// \"05/05/09\";

CGContextSelectFont(context, "Times New Roman", 14, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);

CGContextSetRGBFillColor(context, 0, 0, 0, 1);

//rotate text

CGContextSetTextMatrix(context, CGAffineTransformMakeRotation( -M_PI/8 ));

CGContextShowTextAtPoint(context, 70, 88, text, strlen(text));

CGColorSpaceRelease(colorSpace);

UIGraphicsEndImageContext();
return newImg;

}

In summary, what I have done is add

if (UIGraphicsBeginImageContextWithOptions != NULL) {
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
} else {
    UIGraphicsBeginImageContext(size);
}

Remove

// CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);

and put

CGContextRef context = UIGraphicsGetCurrentContext();

instead. But this causes the image to be upside down. Hence I put

CGContextTranslateCTM(context, 0,h);
CGContextScaleCTM(context, 1.0, -1.0);

just before CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);

This way you can use CG functions instead of using drawInRect etc.

Don't forget

UIGraphicsEndImageContext

at the end. Hope this helps.

Upvotes: 0

fnf
fnf

Reputation: 414

Like Peter said, use UIGraphicsBeginImageContextWithOptions. You might want to pass image.scale to the scale attribute (where image.scale is the scale of one of the images you're drawing), or simply use [UIScreen mainScreen].scale.

This code can be made simpler overall. Try something like:

// Create the image context
UIGraphicsBeginImageContextWithOptions(_baseImage.size, NO, _baseImage.scale);

// Draw the image
CGRect rect = CGRectMake(0, 0, _baseImage.size.width, _baseImage.size.height);
[_baseImage drawInRect:rect];

// Get a vertically centered rect for the text drawing
rect.origin.y = (rect.size.height - FONT_SIZE) / 2 - 2;
rect = CGRectIntegral(rect);
rect.size.height = FONT_SIZE;

// Draw the text
UIFont *font = [UIFont boldSystemFontOfSize:FONT_SIZE];
[[UIColor whiteColor] set];
[text drawInRect:rect withFont:font lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter];

// Get and return the new image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;

Where text is an NSString object.

Upvotes: 5

Related Questions