I want to make an image like this programmatically:
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.
I want to make an image like this programmatically:
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.
Draw text inside an image and return the resulting image:
+(UIImage*) drawText:(NSString*) text
inImage:(UIImage*) image
atPoint:(CGPoint) point
{
UIFont *font = [UIFont boldSystemFontOfSize:12];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x, point.y, image.size.width, image.size.height);
[[UIColor whiteColor] set];
[text drawInRect:CGRectIntegral(rect) withFont:font];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Usage:
// note: replace "ImageUtils" with the class where you pasted the method above
UIImage *img = [ImageUtils drawText:@"Some text"
inImage:img
atPoint:CGPointMake(0, 0)];
Change the origin of the text inside the image from 0,0 to whatever point you like.
To paint a rectangle of solid color behind the text, add the following before the line [[UIColor whiteColor] set];
:
[[UIColor brownColor] set];
CGContextFillRect(UIGraphicsGetCurrentContext(),
CGRectMake(0, (image.size.height-[text sizeWithFont:font].height),
image.size.width, image.size.height));
I'm using the text size to calculate the origin for the solid color rectangle, but you can replace it with any number.
My contribution to the first answer with iOS 7 support :
+(UIImage*) drawText:(NSString*) text
inImage:(UIImage*) image
atPoint:(CGPoint) point
{
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0.0f);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x, point.y, image.size.width, image.size.height);
[[UIColor whiteColor] set];
UIFont *font = [UIFont boldSystemFontOfSize:12];
if([text respondsToSelector:@selector(drawInRect:withAttributes:)])
{
//iOS 7
NSDictionary *att = @{NSFontAttributeName:font};
[text drawInRect:rect withAttributes:att];
}
else
{
//legacy support
[text drawInRect:CGRectIntegral(rect) withFont:font];
}
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Hope this helps
EDIT: modified the UIGraphicsBeginImageContextWithOptions
to handle screen scale. Thk @SoftDesigner
iOS7 only.
Watermark in lower right corner.
@interface UIImage (DrawWatermarkText)
-(UIImage*)drawWatermarkText:(NSString*)text;
@end
@implementation UIImage (DrawWatermarkText)
-(UIImage*)drawWatermarkText:(NSString*)text {
UIColor *textColor = [UIColor colorWithWhite:0.5 alpha:1.0];
UIFont *font = [UIFont systemFontOfSize:50];
CGFloat paddingX = 20.f;
CGFloat paddingY = 20.f;
// Compute rect to draw the text inside
CGSize imageSize = self.size;
NSDictionary *attr = @{NSForegroundColorAttributeName: textColor, NSFontAttributeName: font};
CGSize textSize = [text sizeWithAttributes:attr];
CGRect textRect = CGRectMake(imageSize.width - textSize.width - paddingX, imageSize.height - textSize.height - paddingY, textSize.width, textSize.height);
// Create the image
UIGraphicsBeginImageContext(imageSize);
[self drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
[text drawInRect:CGRectIntegral(textRect) withAttributes:attr];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
@end
Usage:
UIImage *image = [UIImage imageNamed:@"mona_lisa"];
image = [image drawWatermarkText:@"Leonardo da Vinci"];
Here is the Swift version.
func textToImage(drawText: NSString, inImage: UIImage, atPoint:CGPoint)->UIImage{
// Setup the font specific variables
var textColor: UIColor = UIColor.whiteColor()
var textFont: UIFont = UIFont(name: "Helvetica Bold", size: 12)!
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
//Setups up the font attributes that will be later used to dictate how the text should be drawn
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
]
//Put the image into a rectangle as large as the original image.
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
// Creating a point within the space that is as bit as the image.
var rect: CGRect = CGRectMake(atPoint.x, atPoint.y, inImage.size.width, inImage.size.height)
//Now Draw the text into an image.
drawText.drawInRect(rect, withAttributes: textFontAttributes)
// Create a new image out of the images we have created
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
// End the context now that we have the image we need
UIGraphicsEndImageContext()
//And pass it back up to the caller.
return newImage
}
To call it you just pass in an image.
textToImage("000", inImage: UIImage(named:"thisImage.png")!, atPoint: CGPointMake(20, 20))
The following links helped me get this straight.
Swift - Drawing text with drawInRect:withAttributes:
How to write text on image in Objective-C (iOS)?
The original goal was to create a dynamic image that I could use in an AnnotaionView such as putting a price at a given location on a map and this worked out great for it. Hope this helps someone trying to do the same thing.
I did something like this! After browsing and combining some examples.
Puts the text in the midle of the image, resizing the font if needed.
UIImage *myImage = [UIImage imageNamed:@"promoicon.png"];
UIGraphicsBeginImageContext(myImage.size);
[myImage drawInRect:CGRectMake(0,0,myImage.size.width,myImage.size.height)];
UITextView *myText = [[UITextView alloc] init];
myText.font = [UIFont fontWithName:@"TrebuchetMS-Bold" size:15.0f];
myText.textColor = [UIColor whiteColor];
myText.text = NSLocalizedString(@"promotionImageText", @"");
myText.backgroundColor = [UIColor clearColor];
CGSize maximumLabelSize = CGSizeMake(myImage.size.width,myImage.size.height);
CGSize expectedLabelSize = [myText.text sizeWithFont:myText.font
constrainedToSize:maximumLabelSize
lineBreakMode:UILineBreakModeWordWrap];
myText.frame = CGRectMake((myImage.size.width / 2) - (expectedLabelSize.width / 2),
(myImage.size.height / 2) - (expectedLabelSize.height / 2),
myImage.size.width,
myImage.size.height);
[[UIColor whiteColor] set];
[myText.text drawInRect:myText.frame withFont:myText.font];
UIImage *myNewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I have created fully customized extension for UIImage to draw watermark in Swift:
extension UIImage{
enum WaterMarkCorner{
case TopLeft
case TopRight
case BottomLeft
case BottomRight
}
func waterMarkedImage(#waterMarkText:String, corner:WaterMarkCorner = .BottomRight, margin:CGPoint = CGPoint(x: 20, y: 20), waterMarkTextColor:UIColor = UIColor.whiteColor(), waterMarkTextFont:UIFont = UIFont.systemFontOfSize(20), backgroundColor:UIColor = UIColor.clearColor()) -> UIImage{
let textAttributes = [NSForegroundColorAttributeName:waterMarkTextColor, NSFontAttributeName:waterMarkTextFont]
let textSize = NSString(string: waterMarkText).sizeWithAttributes(textAttributes)
var textFrame = CGRectMake(0, 0, textSize.width, textSize.height)
let imageSize = self.size
switch corner{
case .TopLeft:
textFrame.origin = margin
case .TopRight:
textFrame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: margin.y)
case .BottomLeft:
textFrame.origin = CGPoint(x: margin.x, y: imageSize.height - textSize.height - margin.y)
case .BottomRight:
textFrame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: imageSize.height - textSize.height - margin.y)
}
/// Start creating the image with water mark
UIGraphicsBeginImageContext(imageSize)
self.drawInRect(CGRectMake(0, 0, imageSize.width, imageSize.height))
NSString(string: waterMarkText).drawInRect(textFrame, withAttributes: textAttributes)
let waterMarkedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return waterMarkedImage
}
}
As you see, I have added some default values for attributes so you can ignore if you don't need to change. Here some examples for how to use it:
let watermark1 = image.waterMarkedImage(waterMarkText: "@yourapp")
let watermark2 = image.waterMarkedImage(waterMarkText: "your app name", corner: .TopRight, margin: CGPoint(x: 5, y: 5), waterMarkTextColor: UIColor.greenColor())
let watermark3 = image.waterMarkedImage(waterMarkText: "appName", waterMarkTextColor: UIColor.blackColor(), waterMarkTextFont: UIFont(name: "Helvatica", size: 25)!)
extension UIImage
{
enum WaterMarkCorner
{
case TopLeft
case TopRight
case BottomLeft
case BottomRight
}
func waterMarkedImage(text:String, corner:WaterMarkCorner = .BottomRight, margin:CGPoint = CGPoint(x: 20, y: 20), color:UIColor = UIColor.white, font:UIFont = UIFont.systemFont(ofSize: 20), background:UIColor = UIColor.clear) -> UIImage?
{
let attributes = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font:font]
let textSize = NSString(string: text).size(withAttributes: attributes)
var frame = CGRect(x: 0, y: 0, width: textSize.width, height: textSize.height)
let imageSize = self.size
switch corner
{
case .TopLeft:
frame.origin = margin
case .TopRight:
frame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: margin.y)
case .BottomLeft:
frame.origin = CGPoint(x: margin.x, y: imageSize.height - textSize.height - margin.y)
case .BottomRight:
frame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: imageSize.height - textSize.height - margin.y)
}
// Start creating the image with water mark
UIGraphicsBeginImageContext(imageSize)
self.draw(in: CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))
NSString(string: text).draw(in: frame, withAttributes: attributes)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Here is a Swift version which correctly centers the text on the image. This works with text of various sizes.
func addTextToImage(text: NSString, inImage: UIImage, atPoint:CGPoint) -> UIImage{
// Setup the font specific variables
let textColor = YOURCOLOR
let textFont = YOUR SIZE
//Setups up the font attributes that will be later used to dictate how the text should be drawn
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
]
// Create bitmap based graphics context
UIGraphicsBeginImageContextWithOptions(inImage.size, false, 0.0)
//Put the image into a rectangle as large as the original image.
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
// Our drawing bounds
let drawingBounds = CGRectMake(0.0, 0.0, inImage.size.width, inImage.size.height)
let textSize = text.sizeWithAttributes([NSFontAttributeName:textFont])
let textRect = CGRectMake(drawingBounds.size.width/2 - textSize.width/2, drawingBounds.size.height/2 - textSize.height/2,
textSize.width, textSize.height)
text.drawInRect(textRect, withAttributes: textFontAttributes)
// Get the image from the graphics context
let newImag = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImag
}
Use this method to add your textfield on image with selected font and color and size
//Method to add
- (UIImage *) addText:(UIImage *)img text:(NSString *)text
{
CGRect rect = CGRectMake(0,0, img.size.width, img.size.height);
// create a context according to image size
UIGraphicsBeginImageContext(rect.size);
// draw image
[img drawInRect:rect];
float fontSize = _txtvwEdit.font.pointSize*2;
NSLog(@"Original %f new %f",_txtvwEdit.font.pointSize,fontSize);
UIFont* font = [UIFont fontWithName:_txtvwEdit.font.fontName size:fontSize];
CGRect textRect = CGRectMake((_txtvwEdit.frame.origin.x*2)-5,_txtvwEdit.frame.origin.y*2,_txtvwEdit.frame.size.width*2,_txtvwEdit.frame.size.height*2);
if ([temparyGifframes count]>0)
{
font = [UIFont fontWithName:_txtvwEdit.font.fontName size:_txtvwEdit.font.pointSize];
textRect = CGRectMake(_txtvwEdit.frame.origin.x,_txtvwEdit.frame.origin.y ,_txtvwEdit.frame.size.width,_txtvwEdit.frame.size.height);
}
/// Make a copy of the default paragraph style
NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary *attributes = @{ NSFontAttributeName: font, NSForegroundColorAttributeName: _txtvwEdit.textColor,NSParagraphStyleAttributeName: paragraphStyle };
// draw text
[text drawInRect:textRect withAttributes:attributes];
// get as image
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Considering performance, you should avoid having frequent calls to -drawRect:. Every UIView is backed with a CALayer and images as layer contents remain in memory as long as the CALayer stays in the hierarchy.This means that most of the operations you see in an application, including movement, rotation, and scaling of the view/layer, do not require a redraw.This means you can use add an CATextLayer on UIImageView , If you don't need a image with watermark. https://developer.apple.com/library/ios/qa/qa1708/_index.html
- (void)addText:(NSString *)text inImageView:(UIImageView *)imageView {
CATextLayer *textLayer = [CATextLayer layer];
UIFont *font = [UIFont systemFontOfSize:14.0f];
CGSize textSize = [text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14.0f]}];
textLayer.frame = CGRectMake((imageView.size.width - textSize.width)/2,
(imageView.size.height - textSize.height)/2,
textSize.width, textSize.height);;
textLayer.string = text;
textLayer.fontSize = font.pointSize;
[imageView.layer addSublayer:textLayer];
}
In Swift-3 of @Jano Answer :-
func drawText(text:NSString ,image:UIImage ,point:CGPoint ) -> UIImage {
let font = UIFont.boldSystemFont(ofSize: 12)
UIGraphicsBeginImageContext(image.size)
image.draw(in:CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) )
let rect = CGRect(x: point.x, y: point.y, width:image.size.width, height: image.size.height )
UIColor.white.set()
text.draw(in: rect.integral, withAttributes: [NSFontAttributeName : font])
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
Swift 3
extension UIImage {
func textToImage(drawText: NSString, atPoint:CGPoint) -> UIImage? {
// Setup the font specific variables
let textColor: UIColor = UIColor.white
let textFont: UIFont = UIFont(name: "Helvetica Bold", size: 12)!
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(self.size)
//Setups up the font attributes that will be later used to dictate how the text should be drawn
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
] as [String : Any]
//Put the image into a rectangle as large as the original image.
self.draw(in: CGRect(x:0, y:0, width:self.size.width, height: self.size.height))
// Creating a point within the space that is as bit as the image.
let rect: CGRect = CGRect(x:atPoint.x, y:atPoint.y, width:self.size.width, height:self.size.height)
//Now Draw the text into an image.
drawText.draw(in: rect, withAttributes: textFontAttributes)
// Create a new image out of the images we have created
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
// End the context now that we have the image we need
UIGraphicsEndImageContext()
//And pass it back up to the caller.
return newImage
}
}
Swift 3 version of @Hossam Ghareebs answer and added the missing integration of the backgroundColor parameter:
enum WaterMarkCorner{
case TopLeft
case TopRight
case BottomLeft
case BottomRight
}
extension UIImage{
func waterMarkedImage(_ waterMarkText:String, corner:WaterMarkCorner = .TopRight, margin:CGPoint = CGPoint(x: 20, y: 20), waterMarkTextColor:UIColor = UIColor.black, waterMarkTextFont:UIFont = UIFont.systemFont(ofSize: 40), backgroundColor:UIColor = UIColor(white: 1.0, alpha: 0.5)) -> UIImage?{
let textAttributes = [NSForegroundColorAttributeName:waterMarkTextColor, NSFontAttributeName:waterMarkTextFont, NSBackgroundColorAttributeName: backgroundColor]
let textSize = NSString(string: waterMarkText).size(attributes: textAttributes)
var textFrame = CGRect(x:0, y:0, width:textSize.width, height:textSize.height)
let imageSize = self.size
switch corner{
case .TopLeft:
textFrame.origin = margin
case .TopRight:
textFrame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: margin.y)
case .BottomLeft:
textFrame.origin = CGPoint(x: margin.x, y: imageSize.height - textSize.height - margin.y)
case .BottomRight:
textFrame.origin = CGPoint(x: imageSize.width - textSize.width - margin.x, y: imageSize.height - textSize.height - margin.y)
}
/// Start creating the image with water mark
UIGraphicsBeginImageContext(imageSize)
self.draw(in: CGRect(x:0, y:0, width:imageSize.width, height:imageSize.height))
NSString(string: waterMarkText).draw(in: textFrame, withAttributes: textAttributes)
let waterMarkedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return waterMarkedImage
}
}
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 !!!
UIImageView *imageView = [UIImageView alloc];
imageView.image = [UIImage imageNamed:@"img.png"];
UILabel *label = [UILabel alloc];
label.text = @"Your text";
[imageView addsubview:label];
Set the frame of the label where you want the label to be displayed.