How to write text on image in Objective-C (iOS)?

Viewed 84142

I want to make an image like this programmatically:

example

I have the upper image and text with me. Should I write text on the image?

I want to make it a complete .png image(image + label) and set it as the background of the button.

15 Answers

My function can add text water mark on image with 45 degree and 90 degree rotations

+(UIImage *)drawText:(NSString *)text diagonallyOnImage:(UIImage *)image rotation:(WatermarkRotation)rotation{

    UIColor *textColor = [UIColor colorWithRed:255 green:0 blue:0 alpha:0.2];//[UIColor colorWithWhite:0.5 alpha:1.0];
    UIFont *font = [UIFont systemFontOfSize:250];

    // Compute rect to draw the text inside
    NSDictionary *attr = @{NSForegroundColorAttributeName: textColor, NSFontAttributeName: font};
    CGSize textSize = [text sizeWithAttributes:attr];
    CGSize imageSize = image.size;
    // Create a bitmap context into which the text will be rendered.
    UIGraphicsBeginImageContext(textSize);
    // Render the text
    [text drawAtPoint:CGPointMake(0,0) withAttributes:attr];
    // Retrieve the image
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();

    CGImageRef imageRef = [img CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);


    CGContextRef bitmap = CGBitmapContextCreate(NULL, textSize.width, textSize.width, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    switch (rotation) {
        case WatermarkRotation90left:
            CGContextRotateCTM (bitmap, DEGREES_RADIANS(-90));
            CGContextTranslateCTM(bitmap, -textSize.width, 0);
            break;

        case WatermarkRotation90right:
            CGContextRotateCTM (bitmap, DEGREES_RADIANS(90));
            CGContextTranslateCTM(bitmap, 0, -textSize.width);
            break;

        case WatermarkRotation45ltr:
            CGContextRotateCTM (bitmap, DEGREES_RADIANS(45));
            CGContextTranslateCTM(bitmap, textSize.width/4, -textSize.width/2);
            break;

        case WatermarkRotation45rtl:
            CGContextRotateCTM (bitmap, DEGREES_RADIANS(-45));
            CGContextTranslateCTM(bitmap, -textSize.width/2, textSize.width/4);
            break;

        default:
            break;
    }

    CGContextDrawImage(bitmap, CGRectMake(0, (textSize.width/2)-(textSize.height/2), textSize.width, textSize.height), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    UIGraphicsBeginImageContext( imageSize );

    // Use existing opacity as is
    [image drawInRect:CGRectMake(0,0,imageSize.width,imageSize.height)];


    if (rotation == WatermarkRotation90left) {
        [newImage drawInRect:CGRectMake(-((textSize.width/2)-(textSize.height/2)),(imageSize.height/2)-(textSize.width/2),textSize.width,textSize.width) blendMode:kCGBlendModeNormal alpha:1.0];
    }else if(rotation == WatermarkRotation90right){
        [newImage drawInRect:CGRectMake((imageSize.width-textSize.width/2)-(textSize.height/2),(imageSize.height/2)-(textSize.width/2),textSize.width,textSize.width) blendMode:kCGBlendModeNormal alpha:1.0];
    }else{
        [newImage drawInRect:CGRectMake((imageSize.width/2)-(textSize.width/2),(imageSize.height/2)-(textSize.width/2),textSize.width,textSize.width) blendMode:kCGBlendModeNormal alpha:1.0];
    }


    UIImage *mergedImage = UIGraphicsGetImageFromCurrentImageContext();


    UIGraphicsEndImageContext();
    return mergedImage;
}

Enum for rotation:

typedef enum:NSUInteger{
    WatermarkRotation90left=1,
    WatermarkRotation90right,
    WatermarkRotation45ltr,
    WatermarkRotation45rtl
}WatermarkRotation;

Note: Use 0 for drawing watermark in centre of image.(Default case of switch statement)

Add this macro for degree to radian:

#define DEGREES_RADIANS(angle) ((angle) / 180.0 * M_PI)

Hope this helps !!!

I built a solution based on the example provided by @harish-pathak. It takes devices with HiDPI-displays into consideration (size is int, whereas left and top are percent as double).

-(UIImage *)drawText:(NSString *)text onImage:(UIImage *)image withSize:(NSInteger)size posLeft:(double)left posTop:(double)top {
    
    // Get UI scale for HiDPI
    CGFloat scale = [[UIScreen mainScreen] scale];
    
    UIColor *textColor = [UIColor whiteColor];
    UIFont *font = [UIFont fontWithName:@"Font-Name" size:size];
    
    // Compute rect to draw the text inside
    NSDictionary *attr = @{NSForegroundColorAttributeName: textColor, NSFontAttributeName: font};
    CGSize textSize = [text sizeWithAttributes:attr];
    CGSize imageSize = image.size;
    
    // Create a bitmap context into which the text will be rendered
    UIGraphicsBeginImageContextWithOptions(textSize, NO, scale);
    
    // Render the text
    [text drawAtPoint:CGPointMake(0,0) withAttributes:attr];
    // Retrieve the image
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();

    CGImageRef imageRef = [img CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
    
    // Create bitmap context for text
    CGFloat scaledTextWidth = textSize.width * scale;
    CGFloat scaledTextHeight = textSize.height * scale;
    CGContextRef textBitmap = CGBitmapContextCreate(NULL, scaledTextWidth, scaledTextHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
    
    // Scale text for HiDPI devices
    CGContextScaleCTM(textBitmap, scale, scale);
    
    // Draw image for text
    CGRect textPosition = CGRectMake(0, 0, textSize.width, textSize.height);
    CGRect textPixelAligned = CGRectIntegral(textPosition);
    CGContextDrawImage(textBitmap, textPixelAligned, imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(textBitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];
    
    // Create bitmap context into which the image will be rendered
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, scale);

    // Use existing opacity as is
    [image drawInRect:CGRectMake(0,0,imageSize.width,imageSize.height)];
    
    // Create new image with blendmode "normal"
    CGFloat textLeft = (imageSize.width*left)-(textSize.width*0.5);
    CGFloat textTop = (imageSize.height*top)-(textSize.height*0.5);
    CGRect imagePosition = CGRectMake(textLeft,textTop,textSize.width,textSize.height);
    CGRect imagePixelAligned = CGRectIntegral(imagePosition);
    [newImage drawInRect:imagePixelAligned blendMode:kCGBlendModeNormal alpha:1.0];
    
    // Get merged image from context
    UIImage *mergedImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return mergedImage;
}

To center text on image call the function like this:

[self drawText:@"Text" onImage:img withSize:120 posLeft:0.5 posTop:0.5];

Credits to:

Related