Как написать текст на изображении в Objective-C (iOS)?
Я хочу, чтобы изображение, как это программно:
У меня есть верхнее изображение и текст со мной. Должен ли я написать текст на изображении?
Я хочу сделать его полным .png изображение (изображение + метка) и установить его в качестве фона кнопки.
14 ответов:
нарисуйте текст внутри изображения и верните полученное изображение:
+(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; }
использование:
// note: replace "ImageUtils" with the class where you pasted the method above UIImage *img = [ImageUtils drawText:@"Some text" inImage:img atPoint:CGPointMake(0, 0)];
изменить первоначальный текст внутри изображения от 0,0 до любой точки, которая вам нравится.
чтобы нарисовать прямоугольник сплошного цвета позади текста, добавьте следующее перед строкой
[[UIColor whiteColor] set];
:[[UIColor brownColor] set]; CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, (image.size.height-[text sizeWithFont:font].height), image.size.width, image.size.height));
Я использую размер текста для вычисления начала координат для прямоугольника сплошного цвета, но вы можете заменить его любым числом.
мой вклад в первый ответ с поддержкой iOS 7:
+(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; }
надеюсь, что это помогает
EDIT: изменен на
UIGraphicsBeginImageContextWithOptions
для обработки масштаба экрана. Thk @SoftDesigner
только iOS7.
водяной знак в правом нижнем углу.
@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
использование:
UIImage *image = [UIImage imageNamed:@"mona_lisa"]; image = [image drawWatermarkText:@"Leonardo da Vinci"];
вот версия Swift.
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 }
чтобы вызвать его, вы просто передаете изображение.
textToImage("000", inImage: UIImage(named:"thisImage.png")!, atPoint: CGPointMake(20, 20))
следующие ссылки помогли мне получить это прямо.
Swift-рисование текста с drawInRect:withAttributes:
Как написать текст на изображении в Objective-C (iOS)?
первоначальная цель состояла в том, чтобы создать динамическое изображение, которое я мог бы использовать в AnnotaionView, например, поставить цену в заданном месте карта, и это сработало отлично для него. Надеюсь, это поможет кому-то, кто пытается сделать то же самое.
Я сделал что-то подобное! После просмотра и объединения некоторых примеров.
помещает текст в середину изображения, при необходимости изменяя размер шрифта.
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();
Я создал полностью настроенное расширение для UIImage, чтобы нарисовать водяной знак в 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 } }
Как видите, я добавил некоторые значения по умолчанию для атрибутов, так что вы можете игнорировать, если вам не надо менять. Вот несколько примеров того, как его использовать:
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)!)
версия Swift 4.0:
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 } }
вот быстрая версия, которая правильно центрирует текст на изображении. Это работает с текстом различных размеров.
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 }
используйте этот метод, чтобы добавить свой текст на изображение с выбранным шрифтом и цветом и размером
//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; }
учитывая производительность, вы должны избегать частых вызовов-drawRect:. Каждый UIView поддерживается CALayer и изображениями, поскольку содержимое слоя остается в памяти до тех пор, пока CALayer остается в иерархии.Это означает, что большинство операций, которые вы видите в приложении, включая перемещение, поворот и масштабирование вида/слоя, не требуют перерисовки.Это означает, что вы можете использовать добавить CATextLayer на UIImageView , Если вам не нужно изображение с помощью водяной знак. 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]; }
в Swift-3 из @Jano ответ: -
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 версия @Hossam Ghareebs ответ и добавил недостающую интеграцию параметра backgroundColor:
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 } }
моя функция может добавить текст водяной знак на изображение с 45 градусов и 90 градусов вращения
+(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; }
перечисление для вращения:
typedef enum:NSUInteger{ WatermarkRotation90left=1, WatermarkRotation90right, WatermarkRotation45ltr, WatermarkRotation45rtl }WatermarkRotation;
Примечание: используйте 0 для нанесения водяного знака в центре изображения.(По умолчанию оператор switch)
добавить этот макрос для степени Радиан:
#define DEGREES_RADIANS(angle) ((angle) / 180.0 * M_PI)
надеюсь, что это помогает !!!