我想在图像上绘制文字。我已尝试使用CGContextShowTextAtPoint
和NSString
drawAtPoint
,但它们都无法显示带有重音字符的文字(即文本是否为法语)。基本上我希望能够显示unicode字符。任何提示/解决方案?
我使用Core-Graphics(UIImage
类别方法)的解决方案:
- (UIImage *)overlayText:(NSString *)overlayText withFontName:(NSString *)fontName andFontSize:(CGFloat)fontSize {
// Refererence:
// http://iphonesdksnippets.com/post/2009/05/05/Add-text-to-image-%28UIImage%29.aspx
int w = self.size.width;
int h = self.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), self.CGImage);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1);
char *charText = (char *)[overlayText cStringUsingEncoding:NSASCIIStringEncoding];
char *charFontName = (char *)[fontName cStringUsingEncoding:NSASCIIStringEncoding];
CGContextSelectFont(context, charFontName, fontSize, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetRGBFillColor(context, 255, 255, 255, 1);
// rotate text
// CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(-M_PI / 4));
CGFloat textWidth = [overlayText calculateCGTextWidthWithFont:charFontName size:fontSize];
CGFloat xTextPosition = MAX(10.0, w - textWidth - 10.0); // 10.0 inset
CGFloat yTextPosition = 10.0;
CGContextShowTextAtPoint(context, xTextPosition, yTextPosition, charText, strlen(charText));
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage:imageMasked];
}
使用NSString
(UIImage
类别方法)的解决方案:
- (UIImage *)overlayText:(NSString *)overlayText withFontName:(NSString *)fontName andFontSize:(CGFloat)fontSize {
UIFont *font = [UIFont fontWithName:fontName size:fontSize];
char *charFontName = (char *)[fontName cStringUsingEncoding:NSASCIIStringEncoding];
CGFloat textWidth = [overlayText calculateCGTextWidthWithFont:charFontName size:fontSize];
CGFloat xTextPosition = MAX(10.0, self.size.width - textWidth - 10.0); // 10.0 margin/inset
CGFloat yTextPosition = self.size.height - fontSize - 10.0; // 10.0 margin/inset
UIGraphicsBeginImageContext(self.size);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
[[UIColor whiteColor] set];
[overlayText drawAtPoint:CGPointMake(xTextPosition, yTextPosition) withFont:font];
UIImage *overlayTextImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return overlayTextImage;
}
我的核心文本解决方案(UIImage
类别方法):
- (UIImage *)overlayText:(NSString *)overlayText withFontName:(NSString *)fontName andFontSize:(CGFloat)fontSize {
char *charFontName = (char *)[fontName cStringUsingEncoding:NSASCIIStringEncoding];
CGFloat textWidth = [overlayText calculateCGTextWidthWithFont:charFontName size:fontSize];
CGFloat xTextPosition = 10.0; // MAX(10.0, self.size.width - textWidth - 10.0); // 10.0 margin/inset
CGFloat yTextPosition = self.size.height - fontSize - 10.0; // 10.0 margin/inset
UIGraphicsBeginImageContext(self.size);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
// flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// create an attributed string
CFMutableAttributedStringRef attributedOverlayText = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
if (overlayText != nil)
CFAttributedStringReplaceString(attributedOverlayText, CFRangeMake(0, 0), (CFStringRef)overlayText);
CFAttributedStringSetAttribute(attributedOverlayText, CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText)), kCTForegroundColorAttributeName, [[UIColor whiteColor] CGColor]);
CTFontRef ctFont = CTFontCreateWithName((CFStringRef)fontName, fontSize, NULL);
CFAttributedStringSetAttribute(attributedOverlayText, CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText)), kCTFontAttributeName, ctFont);
CFRelease(ctFont);
// draw attributed string using CTLineDraw
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attributedOverlayText);
CGContextSetTextPosition(context, xTextPosition, yTextPosition);
CTLineDraw(line, context);
UIImage *overlayTextImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return overlayTextImage;
}
答案 0 :(得分:0)
我对上述解决方案的问题是,我基本上没有为文本获得正确的“宽度”。
这是适用于我的解决方案(使用Core Text):
- (UIImage *)overlayText:(NSString *)overlayText withFontName:(NSString *)fontName andFontSize:(CGFloat)fontSize {
// Develope's Note:
// Problem with implementing a solution using CG is that it doesn't support unicode character drawing i.e French
// Begin new image context
UIGraphicsBeginImageContext(self.size);
// Draw image
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
// Flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// Create an attributed string
CFMutableAttributedStringRef attributedOverlayText = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
if (overlayText != nil)
CFAttributedStringReplaceString(attributedOverlayText, CFRangeMake(0, 0), (__bridge CFStringRef)overlayText);
// Set text color
CFAttributedStringSetAttribute(attributedOverlayText,
CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText)),
kCTForegroundColorAttributeName,
[[UIColor whiteColor] CGColor]);
// Set text font
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)fontName, fontSize, NULL);
CFAttributedStringSetAttribute(attributedOverlayText,
CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText)),
kCTFontAttributeName,
ctFont);
CFRelease(ctFont);
// Set text alignment (paragraph style)
CTTextAlignment alignment = kCTRightTextAlignment;
CTParagraphStyleSetting settings[] = {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
CFAttributedStringSetAttribute(attributedOverlayText,
CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText)),
kCTParagraphStyleAttributeName,
paragraphStyle);
CFRelease(paragraphStyle);
// Create framesetter with the attributed text
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributedOverlayText);
CFRange stringRange = CFRangeMake(0, CFAttributedStringGetLength(attributedOverlayText));
CGSize fitRange = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
CFRangeMake(0, 0),
NULL,
CGSizeMake(self.size.width - (2 * 10.0), CGFLOAT_MAX),
NULL);
// Developer's Note:
// We can't use fontSize for the framesetter's height.
// We can't use fitRange.height in the bounding rectangle, because then we won't get the correct text alignment
// Calculate the width (and correspondingly the xTextPosition)
CGRect boundingRect = CGRectMake(10.0,
10.0,
self.size.width - (2 * 10.0),
fitRange.height);
CGMutablePathRef boundingPath = CGPathCreateMutable();
CGPathAddRect(boundingPath, NULL, boundingRect);
// Draw attributed text using CTFrameDraw
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, stringRange, boundingPath, NULL);
CTFrameDraw(frame, context);
CFRelease(framesetter);
// Draw boundary (debugging purposes only)
if (NO) {
// Inner boundary
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextStrokeRect(context, CGPathGetBoundingBox(boundingPath));
// Outer boundary
CGMutablePathRef controlBoundaryPath = CGPathCreateMutable();
CGPathAddRect(controlBoundaryPath, NULL, CGRectMake(0, 0, self.size.width, self.size.height));
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextStrokeRect(context, CGPathGetBoundingBox(controlBoundaryPath));
CFRelease(controlBoundaryPath);
}
// Draw attributed string using CTLineDraw
// (Doesn't work if we want to right align the text)
// CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attributedOverlayText);
// CGContextSetTextPosition(context, xTextPosition, yTextPosition);
// CTLineDraw(line, context);
UIImage *overlayTextImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return overlayTextImage;
}
希望这有助于某人。