Как написать текст на изображении в Objective-C (iOS)?


Я хочу, чтобы изображение, как это программно:

У меня есть верхнее изображение и текст со мной. Должен ли я написать текст на изображении?

Я хочу сделать его полным .png изображение (изображение + метка) и установить его в качестве фона кнопки.

14 73

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)

надеюсь, что это помогает !!!

UIImageView *imageView = [UIImageView alloc];
imageView.image = [UIImage imageNamed:@"img.png"];
UILabel *label = [UILabel alloc];
label.text = @"Your text";
[imageView addsubview:label];

установите рамку метки там, где она должна отображаться.