Search code examples
xcodensstringuiimagefont-sizeautoresize

Scale NSString Font to UIImage Size


I'm writing text onto a image taken from the iDevice's camera or chosen from the photo library but I need the fontsize scaled according to width/height of the image. Here's my current code: UIGraphicsBeginImageContext(img.size);

CGRect aRectangle = CGRectMake(0,0, img.size.width, img.size.height);
[img drawInRect:aRectangle];

[[UIColor whiteColor] set];           // set text color
NSInteger fontSize = 45;
UIFont *font = [UIFont systemFontOfSize:fontSize];// set text font

[ text drawInRect : aRectangle                      // render the text
         withFont : font
    lineBreakMode : UILineBreakModeTailTruncation  // clip overflow from end of last line
        alignment : UITextAlignmentCenter ];

UIImage *theImage=UIGraphicsGetImageFromCurrentImageContext();   // extract the image
UIGraphicsEndImageContext();     // clean  up the context.
return theImage;</i>

Solution

  • You want something like this. It creates a rect half the size of your image, then uses a binary search to zoom in on the font size you want.

    //---- initial data
    CGSize szMax = CGSizeMake(<imgWidth> / 2, <imgHeight> / 2);
    CGFloat fMin = 2;      //-- the smallest size font we want
    CGFloat fMax = 100;    //-- the largest size font we want
    CGFloat fMid;          //-- the middle of min and max
    
    while ((fMax - fMin) >= 1.0)    //-- repeat until the sizes converge
    {
        fMid = (fMin + fMax) / 2.0;    //-- compute mid-point
    
        UIFont *pfnt = [UIFont systemFontOfSize: fMid];    //-- create middle-sized font
    
        //---- compute the size of the text using the mid-sized font
        CGSize szStr = [pStr sizeWithFont: pfnt constrainedToSize: szMax lineBreakMode: UILineBreakModeWordWrap];
    
        if (szStr.height > szMax.height)
            fMax = fMid;                //-- text too tall, set max to mid-point
        else               
            fMin = fMid;                //-- text too short, set min to mid-point
    }
    //---- 'fMid' is the size you want.