0

I'm using this answer to put text over my UIImage (method 2). The problem is, the text comes out incredibly blurry, and also is not horizontally and vertically centered. Here is a screenshot of the behavior:

screen

How could I fix this?

My code to add the text in is this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MainCell"];

    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MainCell"];
    }

    NSString *metaScore =  _getString([[news objectAtIndex:indexPath.row] objectForKey:@"metaScore"]);
    NSString *title = _getString([[news objectAtIndex:indexPath.row] objectForKey:@"title"]);
    NSString *releaseDate =  _getString([[news objectAtIndex:indexPath.row] objectForKey:@"releaseDate"]);
    NSString *type =  _getString([[news objectAtIndex:indexPath.row] objectForKey:@"type"]);
    NSString *rating =  _getString([[news objectAtIndex:indexPath.row] objectForKey:@"rating"]);

    [cell.textLabel setLineBreakMode:NSLineBreakByWordWrapping];
    cell.textLabel.text = title;
    cell.detailTextLabel.numberOfLines = 4;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@\n%@\n%@", releaseDate, type, rating];

    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(0, 0, 50, 50);

    imageView.image = [self addText:[UIImage imageNamed:@"green.png"] text:metaScore];
    cell.image = imageView.image;

    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];

    return cell;
}

-(UIImage *)addText:(UIImage *)img text:(NSString *)text1{
    int w = img.size.width;
    int h = img.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);

    char* text= (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];
    CGContextSelectFont(context, "Arial", 20, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode(context, kCGTextFill);
    CGContextSetRGBFillColor(context, 256, 256, 256, 1);
    CGContextShowTextAtPoint(context, 20, 20, text, strlen(text));
    CGImageRef imgCombined = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    UIImage *retImage = [UIImage imageWithCGImage:imgCombined];
    CGImageRelease(imgCombined);

    return retImage;
}
Community
  • 1
  • 1
Witch-King
  • 283
  • 1
  • 5
  • 13
  • You have to do the math for Horizontal/Vertical scrolling http://stackoverflow.com/questions/9637682/using-cgcontextshowtextatpoint-how-to-do-left-and-right-text-justification – Justin Meiners Aug 22 '13 at 21:19
  • That image looks low resolution itself, that looks like as good as the text could be at that resolution... Render it on a bigger image? – Justin Meiners Aug 22 '13 at 21:19
  • 1
    because probably the text width and/or height is an odd number and probably the center-point would be rather fraction pixels than whole ones... – holex Aug 22 '13 at 21:20
  • That answer is a little ambiguous. Could you post some real code? – Witch-King Aug 22 '13 at 21:21
  • The image has to be 50px by 50px. I'm rendering it on a uitableviewcell. – Witch-King Aug 22 '13 at 21:21
  • @Witch-King, that is just a comment, not an answer. anyway, the width/height of the text could be odd number (e.g. 49px), and when you just divided by 2 (for finding the center-point) you will get a fraction pixel (24.5px), which is a valid value, it won't be rounded to any whole, the `CoreGraphics` is just 'playing' with the alpha channel to make the text anti-aliased. that is why you get that result. – holex Aug 22 '13 at 21:27
  • @Witch-King why not just use a UILabel if its on a cell? (one is already on the cell if you want) – Justin Meiners Aug 22 '13 at 21:28
  • Really? There's a label on the cell? – Witch-King Aug 22 '13 at 21:29
  • Post your code that positions and places this text on the UIImage, that'll make it easier for everyone involved. – WDUK Aug 22 '13 at 23:01
  • Did it. Check my update. – Witch-King Aug 22 '13 at 23:11

1 Answers1

3

It's possible you're not drawing your text on pixel-aligned boundaries.

For example, if you position your text at x:12.4, y:18.7, then the text won't render crisp, as they're not aligned to the pixels on screen. For a standard display, you need positions and sizes to be whole numbers (they can't be fractions). For retina displays, you can get away by having half points, but it's usually easier to keep them as whole numbers too.

If you're using CGRect to determine the position of the text, you can use CGRectIntegral() to align them for you. This will floor the positions, and ceiling the sizes. For example:

CGRect position = CGRectMake(12.2, 17.8, 44.7, 49.2);
position = CGRectIntegral(position);
/* Position is now
   x: 12, y: 17
   w: 45, h: 50
*/

If you're doing it without a CGRect, you can use floor/floorf and ceil/ceilf (using the f variant if you're using CGFloats)

Edit: Remember CoreGraphics works with pixels and not points, as such you need to take into account the scale factor in any of your calculations. Thankfully, CoreGraphics makes that a bit easier than you'd think. Simply insert this straight after you've created your context. This will set the correct scale for any future calculations within that context.

CGFloat scale = [[UIScreen mainScreen] scale];
CGContextScaleCTM(context, scale, scale);

As for the alignment of text, this won't be easy. You're manually setting it to (20,20), which will set the position of the top left corner of the first character. This is unlikely to center your text. As you don't know the rendered width and height of the text though, you can't compensate for the position of the top left corner to make the text centered. You'll struggle here, but once you can find out the rendered width and height of the text, you can calculate the correct position using this and the width/height of the image.

WDUK
  • 18,870
  • 3
  • 64
  • 72
  • Using your code sample, this is the resulting UIImage I have: http://i.imgur.com/gMnrhiZ.png But when viewed on a retina device, you get the blurriness. To remedy this, you need to take into account the screen's scale factor. I'll update my answer. – WDUK Aug 23 '13 at 00:16
  • So I put this right after `CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);`? It's still blurry. – Witch-King Aug 23 '13 at 16:57