Je veux faire une image comme celle-ci par programme:
J'ai l'image supérieure et le texte avec moi. Dois-je écrire du texte sur l'image?
Je veux en faire une image .png complète (image + étiquette) et la définir comme arrière-plan du bouton.
Dessinez du texte à l'intérieur d'une image et renvoyez l'image résultante:
+(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)];
Modifiez l’origine du texte dans l’image de 0,0 à votre guise.
Pour peindre un rectangle de couleur unie derrière le texte, ajoutez ce qui suit avant la ligne [[UIColor whiteColor] set];
:
[[UIColor brownColor] set];
CGContextFillRect(UIGraphicsGetCurrentContext(),
CGRectMake(0, (image.size.height-[text sizeWithFont:font].height),
image.size.width, image.size.height));
J'utilise la taille du texte pour calculer l'origine du rectangle de couleur unie, mais vous pouvez le remplacer par n'importe quel nombre.
Ma contribution à la première réponse avec le support 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;
}
J'espère que cela t'aides
EDIT: a modifié la UIGraphicsBeginImageContextWithOptions
pour gérer l'échelle de l'écran. Merci @SoftDesigner
Voici la version 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
}
Pour l'appeler, il suffit de passer une image.
textToImage("000", inImage: UIImage(named:"thisImage.png")!, atPoint: CGPointMake(20, 20))
Les liens suivants m'ont aidé à comprendre.
Swift - Dessiner du texte avec drawInRect: withAttributes:
Comment écrire du texte sur l'image dans Objective-C (iOS)?
L'objectif initial était de créer une image dynamique que je pouvais utiliser dans un AnnotaionView, par exemple pour mettre un prix à un emplacement donné sur une carte et cela fonctionnait parfaitement. J'espère que cela aide quelqu'un qui essaie de faire la même chose.
iOS7 uniquement.
Filigrane dans le coin inférieur droit.
@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"];
J'ai fait quelque chose comme ça! Après avoir parcouru et combiné quelques exemples.
Place le texte au centre de l'image, redimensionnant la police si nécessaire.
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();
J'ai créé une extension entièrement personnalisée pour UIImage afin de dessiner un filigrane dans 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
}
}
Comme vous le voyez, j'ai ajouté quelques valeurs par défaut pour les attributs afin que vous puissiez les ignorer si vous n'avez pas besoin de changer. Voici quelques exemples d'utilisation:
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
}
}
Voici une version de Swift qui centre correctement le texte sur l'image. Cela fonctionne avec du texte de différentes tailles.
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
}
Utilisez cette méthode pour ajouter votre champ de texte sur l'image avec la police, la couleur et la taille sélectionnées.
//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;
}
Dans Swift-3 de @Jano Réponse: -
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!
}
Ma fonction peut ajouter une marque de fond de texte sur l'image avec des rotations de 45 et 90 degrés
+(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 pour la rotation:
typedef enum:NSUInteger{
WatermarkRotation90left=1,
WatermarkRotation90right,
WatermarkRotation45ltr,
WatermarkRotation45rtl
}WatermarkRotation;
Remarque: utilisez 0 pour dessiner un filigrane au centre de l'image (cas par défaut de l'instruction switch).
Ajoutez cette macro pour degré à radian:
#define DEGREES_RADIANS(angle) ((angle) / 180.0 * M_PI)
J'espère que cela t'aides !!!
Vu les performances, vous devriez éviter d'avoir des appels fréquents à -drawRect :. Chaque UIView est soutenu avec une couche CAL et les images en tant que contenu des couches restent en mémoire tant que la couche CAL reste dans la hiérarchie. Cela signifie que la plupart des opérations que vous voyez dans une application, notamment le mouvement, la rotation et la mise à l'échelle de la vue/couche Cela ne signifie pas que vous pouvez utiliser ajouter un CATextLayer sur UIImageView. Si vous n’avez pas besoin d’une image avec filigrane . 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];
}
La version 3 de @Hossam Ghareebs de Swift répond Et ajoute l’intégration manquante du paramètre 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
}
}
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
}
}