I am creating an image with UIImage, and overlaying some text on top.
The end result is coming out blurry, and I want it to be clear
UIImage* DrawTextOnImage(NSString *text, UIImage *image)
{
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0.0);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGRect rect = CGRectMake(10, 50, image.size.width-20, image.size.height-60);
NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraph.lineBreakMode = NSLineBreakByWordWrapping;
paragraph.alignment = NSTextAlignmentCenter;
NSShadow *shadow = [NSShadow.alloc init];
shadow.shadowColor = [UIColor clearColor];
NSDictionary *attributes = #{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont systemFontOfSize:18], NSParagraphStyleAttributeName:paragraph, NSShadowAttributeName:shadow};
[text drawInRect:CGRectIntegral(rect) withAttributes:attributes];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I have seen others having problems when setting the scale wrong, but changing it doesn't affect mine.
Anyone else having similar issues?
Related
I need draw string with stroke ,then convert to a UIImage, but in ios 13.7, the "stroke" 's new line not match to "fill" 's new line,
error in ios 13.7:
correct in ios 14 ,16:
after some test ,i find if i don't set NSParagraphStyleAttributeName in attributes, new line is right in ios 13.7 ,it's a bug in ios 13.7?
my code:
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *img = [[self class] drawTextWithStroke];
UIImageView* imageView = [[UIImageView alloc] initWithImage:img];
[self.view addSubview:imageView];
}
+ (UIImage*)drawTextWithStroke
{
NSString* string = #"The operation couldn’t be completed. completed";
CGRect rect = CGRectMake(0, 0, 362, 42);
CGSize size = CGSizeMake(rect.size.width, rect.size.height);
UIFont *font = [UIFont fontWithName:#"Arial-BoldMT" size:18];
// retina display, double resolution
if ([UIScreen instancesRespondToSelector:#selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f) {
UIGraphicsBeginImageContextWithOptions(size, NO, 2.0f);
} else {
UIGraphicsBeginImageContext(size);
}
CGContextRef context = UIGraphicsGetCurrentContext();
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
//
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setAlignment: NSTextAlignmentCenter];
attributes[ NSParagraphStyleAttributeName ] = style;
// draw stroke
[attributes setObject:font forKey:NSFontAttributeName];
[attributes setObject:[NSNumber numberWithFloat:3] forKey:NSStrokeWidthAttributeName];
[attributes setObject:[UIColor redColor] forKey:NSStrokeColorAttributeName];
[string drawInRect:rect withAttributes:attributes];
// draw fill
[attributes removeObjectForKey:NSStrokeWidthAttributeName];
[attributes removeObjectForKey:NSStrokeColorAttributeName];
[attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
[string drawInRect:rect withAttributes:attributes];
// convert to image and return
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The best solution is to draw the text just once specifying both the stroke and the fill attributes together.
But here's the trick - you need to specify a negative stroke width in order to get both the stroke and fill. If you go to the documentation for the NSStrokeWidthAttributeName key you will see the following (emphasis mine):
The value of this attribute is an NSNumber object containing a floating-point value. This value represents the amount to change the stroke width and is specified as a percentage of the font point size. Specify 0 (the default) for no additional changes. Specify positive values to change the stroke width alone. Specify negative values to stroke and fill the text. For example, a typical value for outlined text would be 3.0.
So changing your stroke width to a negative number gives you the desired effect.
Here's an updated version of your code with lots of little cleanup.
+ (UIImage*)drawTextWithStroke {
NSString* string = #"The operation couldn’t be completed. completed";
CGRect rect = CGRectMake(0, 0, 362, 42);
// Added in iOS 4.0 - no need to check for it any more
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
//
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setAlignment: NSTextAlignmentCenter];
attributes[ NSParagraphStyleAttributeName ] = style;
UIFont *font = [UIFont fontWithName:#"Arial-BoldMT" size:18];
attributes[NSFontAttributeName] = font;
attributes[NSStrokeWidthAttributeName] = #(-3); // Use negative value for both stroke and fill
attributes[NSStrokeColorAttributeName] = UIColor.redColor;
attributes[NSForegroundColorAttributeName] = UIColor.blackColor;
[string drawInRect:rect withAttributes:attributes];
// convert to image and return
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I am trying to draw an image and some text on a UISlider thumbnail. I have the following code that works fine on iOS 12 and below, but does not on iOS 13 and above(specifically iOS 13.2).
- (UIImage*)getSliderImageWithImage:(UIImage*)bgImage valueText:(NSString*)value {
CGFloat scale = 5.0;
//Drawing BG Image
// Where bg image is some image on top of which i need to render text.
UIGraphicsBeginImageContextWithOptions(CGSizeMake(bgImage.size.width * scale, bgImage.size.height * scale), NO, 1);
// This works
[bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width * scale, bgImage.size.height * scale)];
CGRect valueBgRect;
UIColor * textColor;
UIFont * textFont;
textColor = [UIColor whiteColor];
valueBgRect = CGRectMake(18,40, bgImage.size.width,bgImage.size.height);
textFont = [UIFont fontWithName:#"Helvetica-Bold" size:50];
NSDictionary *attrsValue = #{ NSForegroundColorAttributeName : textColor,
NSFontAttributeName : textFont,
NSTextEffectAttributeName : NSTextEffectLetterpressStyle};
// This doesn't.
[value drawInRect:valueBgRect withAttributes:attrsValue];
// Though I can see the image, the text that should be on top of it is not visible.
UIImage *theImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage; }
I also tried setting the text on a UILabel and rendering using
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
and
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
But none of these work. Since this a very common scenario, I am surprised that I cannot find any mention of such an issue in iOS 13.2. That leads met to think that I must be looking at it the wrong way. Can anyone please help ?
It's working in iOS 13
_imgView.image = [self drawFront:[UIImage imageNamed:#"chain_image.jpeg"] text:#"SANKET VAGHELA" atPoint:CGPointMake(50, 50)];
Call this function.
-(UIImage*)drawFront:(UIImage*)image text:(NSString*)text atPoint:
(CGPoint)point
{
UIFont *font = [UIFont systemFontOfSize:20];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x, (point.y - 5), image.size.width, image.size.height);
[[UIColor whiteColor] set];
NSMutableAttributedString* attString = [[NSMutableAttributedString alloc] initWithString:text];
NSRange range = NSMakeRange(0, [attString length]);
[attString addAttribute:NSFontAttributeName value:font range:range];
[attString addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:range];
NSShadow* shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(1.0f, 1.5f);
[attString addAttribute:NSShadowAttributeName value:shadow range:range];
[attString drawInRect:CGRectIntegral(rect)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I need round and text on the round on UIImage like this Image
Sample Image here
Here is my code which i achieved already but with square not in round, i need round around the text.
+(UIImage*)drawText:(NSString*)text inImage:(UIImage*)image atPoint:(CGPoint)point
{
UIFont *font = [UIFont boldSystemFontOfSize:50];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x - 10, point.y - 10, image.size.width, image.size.height);
[text drawInRect:CGRectIntegral(rect) withAttributes:#{NSFontAttributeName:font,NSBackgroundColorAttributeName:[UIColor colorWithRed:0.26 green:0.32 blue:0.59 alpha:1.0],NSForegroundColorAttributeName:[UIColor whiteColor]}];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Thanks in advance.
Do something like that:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.imgview.image = [ViewController drawText:#"iOS" inImage:[UIImage imageNamed:#"eye"] atPoint:CGPointMake(30 , 30)];
self.imgview.layer.cornerRadius = self.imgview.frame.size.height/2;
self.imgview.clipsToBounds = YES;
}
+ (UIImage*)drawText:(NSString*)text inImage:(UIImage*)image atPoint:(CGPoint)point
{
UIFont *font = [UIFont boldSystemFontOfSize:20];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x - 10, point.y - 10, image.size.width, image.size.height);
[text drawInRect:CGRectIntegral(rect) withAttributes:#{NSFontAttributeName:font,NSBackgroundColorAttributeName:[UIColor colorWithRed:0.26 green:0.32 blue:0.59 alpha:1.0],NSForegroundColorAttributeName:[UIColor whiteColor]}];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
UPDATE
For this you have to add some more logic like below.
- (void)viewDidLoad {
[super viewDidLoad];
self.imgview.image = [ViewController drawText:#"iOS Dev" inImage:[UIImage imageNamed:#"Lion"] bgCircleRect:CGRectMake(15, 15, 100, 100)];
}
+ (UIImage*)drawText:(NSString*)text inImage:(UIImage*)image bgCircleRect:(CGRect) bgCircleRect
{
UIFont *font = [UIFont boldSystemFontOfSize:20];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(bgCircleRect.origin.x+10, bgCircleRect.origin.y+35, bgCircleRect.size.width, bgCircleRect.size.height);
UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect: bgCircleRect cornerRadius: 50];
[UIColor.redColor setFill];
[path fill];
[text drawInRect:CGRectIntegral(rect) withAttributes:#{NSFontAttributeName:font,NSBackgroundColorAttributeName:[UIColor redColor],NSForegroundColorAttributeName:[UIColor whiteColor]}];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Output
For making the UIImageView round, First check whether the length and width is same, then apply the following code in the viewDidLoad()
yourpic.layer.cornerRadius = yourpic.frame.size.width / 2;
yourpic.clipsToBounds = YES;
I think this will do.
I think you are looking for corner radius :
+(void)drawText:(NSString*)text inImage:(UIImage*)image atPoint:(CGPoint)point{
UIImageView *imageView = [[UIImageView alloc] init];
UIFont *font = [UIFont boldSystemFontOfSize:50];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x - 10, point.y - 10, image.size.width, image.size.height);
[text drawInRect:CGRectIntegral(rect) withAttributes:#{NSFontAttributeName:font,NSBackgroundColorAttributeName:[UIColor colorWithRed:0.26 green:0.32 blue:0.59 alpha:1.0],NSForegroundColorAttributeName:[UIColor whiteColor]}];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.center = point;
imageView.image = newImage; }
Add image to imageView and add that as subView to your main view
I need to rotate the String and save this rotating string as UIImage.
Let say my given String is = HELLO WORLD
Now i need to first rotate(say 45 degree) it and than saved as UIImage so i can show this UIImage into my UIImageView
Please help me . So i can rotate the String and save this rotating string as UIImage in Swift?.
I found this answer Drawing rotated text with NSString drawInRect. But not able to achieve the result.
May be the below code helps u,I achieved the same result of rotating the string in 45 degree
-(UIImage*) drawText:(NSString*) text
atPoint:(CGPoint) point
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(65, 65),NO,0.0);
CGRect rect = CGRectMake(point.x, point.y, 50, 30);
[[UIColor whiteColor] set];
CGContextConcatCTM(UIGraphicsGetCurrentContext(), CGAffineTransformMakeTranslation(32.5, 32.5));
CGContextConcatCTM(UIGraphicsGetCurrentContext(), CGAffineTransformMakeRotation(M_PI / 4));
CGContextConcatCTM(UIGraphicsGetCurrentContext(), CGAffineTransformMakeTranslation(-32.5, -32.5));
//[text drawInRect:CGRectIntegral(rect) withFont:font ];
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[paragraphStyle setAlignment:NSTextAlignmentCenter];
NSDictionary *attributes = #{ NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-CondensedBold" size:12],
NSForegroundColorAttributeName: [UIColor blackColor],
NSParagraphStyleAttributeName:paragraphStyle};
[text drawInRect:CGRectIntegral(rect) withAttributes:attributes];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Below is screenshot where i achieved the result
hi all i have looked at answers to similar questions and none seem to work for me. I am trying to water mark an image from the camera (image in the below) and add an image and text as a water mark. The below is working perfectly for adding the image but have no idea how to do the text.
WmarkImage = [UIImage imageNamed:#"60.png"];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
[WmarkImage drawInRect:CGRectMake(image.size.width - WmarkImage.size.width, image.size.height - WmarkImage.size.height, WmarkImage.size.width, WmarkImage.size.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[imageView setImage:image];
You should convert your text to image then merge them here is an code for this please check this.
NSString* kevin = #"Hello";
UIFont* font = [UIFont systemFontOfSize:12.0f];
CGSize size = [kevin sizeWithFont:font];
// Create a bitmap context into which the text will be rendered.
UIGraphicsBeginImageContext(size);
// Render the text
[kevin drawAtPoint:CGPointMake(0.0, 0.0) withFont:font];
// Retrieve the image
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIImage *MergedImage = [UIImage imageNamed:#"mark.png"];
CGSize newSize = CGSizeMake(200, 400);
UIGraphicsBeginImageContext( newSize );
// Use existing opacity as is
[MergedImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Apply supplied opacity if applicable
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 20, 300, 400)];
[imageView setImage:newImage];
[self.view addSubview:imageView];
This might help..
CATextLayer *theTextLayer = [CATextLayer layer];
theTextLayer.string = #"Your Text here";
theTextLayer.font = #"Helvetica";
theTextLayer.fontSize = #"12"
theTextLayer.alignmentMode = kCAAlignmentCenter;
theTextLayer.bounds = CGRectMake(0, 0, 40, 40);//give whatever width or height you want
[imageview.layer addSubLayer:theTextLayer];