Я хочу зробити подібне зображення програмним способом:
У мене є верхнє зображення та текст із собою. Чи слід писати текст на зображенні?
Я хочу зробити його повним .png-зображенням (зображення + мітка) і встановити його як фон кнопки.
Я хочу зробити подібне зображення програмним способом:
У мене є верхнє зображення та текст із собою. Чи слід писати текст на зображенні?
Я хочу зробити його повним .png-зображенням (зображення + мітка) і встановити його як фон кнопки.
Відповіді:
Намалюйте текст всередині зображення і поверніть отримане зображення:
+(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
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0.0f);
Ось версія 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, наприклад, встановити ціну на певному місці на карті, і це чудово для нього вийшло. Сподіваюся, це допомагає тому, хто намагається зробити те саме.
Лише для 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"];
Я зробив щось подібне! Після перегляду та комбінування деяких прикладів.
Розміщує текст у середній частині зображення, за потреби змінюючи розмір шрифту.
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)!)
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
}
}
Ось версія Swift, яка правильно центрує текст на зображенні. Це працює з текстом різного розміру.
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;
}
У 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!
}
Стрімкий 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 для малювання водяного знаку в центрі зображення. (Типовий випадок оператора перемикача)
Додайте цей макрос градуса до радіана:
#define DEGREES_RADIANS(angle) ((angle) / 180.0 * M_PI)
Сподіваюся, це допомагає !!!
Враховуючи продуктивність, слід уникати частих дзвінків на -drawRect:
. Кожне з UIView
них підкріплено символом a, CALayer
а зображення, оскільки вміст шару залишається в пам'яті до тих пір, поки CALayer
залишається в ієрархії. вимагає redraw.This кошти , які можна використовувати додайте CATextLayer
в UIImageView
, якщо вам не потрібно зображення з водяним знаком.
https://developer.apple.com/library/ios/qa/qa1708/_index.html
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];
}
UIImageView *imageView = [UIImageView alloc];
imageView.image = [UIImage imageNamed:@"img.png"];
UILabel *label = [UILabel alloc];
label.text = @"Your text";
[imageView addsubview:label];
Встановіть рамку етикетки там, де потрібно, щоб вона відображалася.