如何在Cocoa Objective-C中将Text转换为Image

时间:2012-07-11 23:24:16

标签: objective-c cocoa

我正在寻找一种方法将一段文本转换为Cocoa中的图像。一切似乎都描述了将图像转换为文本而不是文本转换为图像。

简单地说,我想说一句话(例如“Kevin”)并将其转换为位图图像以进行操作并保存为JPEG。

给予答案的人很棒。感谢您提供三种不同且同样有效的方法(是的,我已经对它们进行了测试)....非常酷我希望我能给你所有正确答案。

4 个答案:

答案 0 :(得分:7)

编辑:我误解了这个问题,并假设你想要Cocoa-touch代码(如果你这么做的话,我已经把它留在了最后)。下面是使用CoreText在Cocoa中执行此操作的一种方法(另一张海报说有很多方法):

{
    NSString* string = @"Kevin";
    CGFloat fontSize = 12.0f;

    // Create an attributed string with string and font information
    CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica Light"), fontSize, nil);
    NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                (id)font, kCTFontAttributeName, 
                                nil];
    NSAttributedString* as = [[NSAttributedString alloc] initWithString:string attributes:attributes];
    CFRelease(font);

    // Figure out how big an image we need 
    CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)as);
    CGFloat ascent, descent, leading;
    double fWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);

    // On iOS 4.0 and Mac OS X v10.6 you can pass null for data 
    size_t width = (size_t)ceilf(fWidth);
    size_t height = (size_t)ceilf(ascent + descent);
    void* data = malloc(width*height*4);

    // Create the context and fill it with white background
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
    CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, width*4, space, bitmapInfo);
    CGColorSpaceRelease(space);
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); // white background
    CGContextFillRect(ctx, CGRectMake(0.0, 0.0, width, height));

    // Draw the text 
    CGFloat x = 0.0;
    CGFloat y = descent;
    CGContextSetTextPosition(ctx, x, y);
    CTLineDraw(line, ctx);
    CFRelease(line);

    // Save as JPEG
    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage:imageRef];
    NSAssert(imageRep, @"imageRep must not be nil");
    NSData* imageData = [imageRep representationUsingType:NSJPEGFileType properties:nil];
    NSString* fileName = [NSString stringWithFormat:@"Kevin.jpg"];
    NSString* fileDirectory = NSHomeDirectory();
    NSString* filePath = [fileDirectory stringByAppendingPathComponent:fileName];
    [imageData writeToFile:filePath atomically:YES];

    // Clean up
    [imageRep release];
    CGImageRelease(imageRef);
    free(data);
}

这是可可触摸版:

// Figure out the dimensions of the string in a given font.
NSString* kevin = @"Kevin";
UIFont* font = [UIFont systemFontOfSize:12.0f];
CGSize size = [kevin sizeWithFont:font];
// Create a bitmap context into which the text will be rendered.
UIGraphicsBeginImageContext(size);
// Render the text 
[kevin drawAtPoint:CGPointMake(0.0, 0.0) withFont:font];
// Retrieve the image
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
// Convert to JPEG
NSData* data = UIImageJPEGRepresentation(image, 1.0);
// Figure out a safe path
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(
                                    NSDocumentDirectory,
                                    NSUserDomainMask,
                                    YES);
NSString *docDir = [arrayPaths objectAtIndex:0];
// Write the file
NSString *filePath = [docDir stringByAppendingPathComponent:@"Kevin.jpg"];
BOOL success = [data writeToFile:filePath atomically:YES];
if(!success)
{
    NSLog(@"Failed to write to file. Perhaps it already exists?");
}
else
{
    NSLog(@"JPEG file successfully written to %@", filePath);
}
// Clean up
UIGraphicsEndImageContext();

当我开始iOS编程时,我发现以下内容不直观或不寻常。测量和绘制字符串的方法是NSString上的方法(不像其他系统那样是图形上下文)。保存数据的方法是NSData上不是文件类的方法!创建图形上下文的函数是普通的C函数,而不是任何类的一部分。

希望这有帮助!

答案 1 :(得分:5)

(幸运或不幸的是)有许多不同的方法可以做到这一点。

版本1:仅适用于AppKit / Foundation

NSString *text = ...;
NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSFont fontWithName:@"Helvetica" size:24], NSFontAttributeName,
    nil];
NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(250, 250)];
[img lockFocus];
[text drawAtPoint:NSMakePoint(10, 10) withAttributes:attr];
[img unlockFocus];

// when you want to write it to a JPEG
NSData *dat = [NSBitmapImageRep
    representationOfImageRepsInArray:[img representations]
    usingType:NSJPEGFileType
    properties:[NSDictionary dictionaryWithObjectsAndKeys:
        [NSNumber numberWithFloat:0.9], NSImageCompressionFactor,
        nil]];

然后,您可以根据需要将dat写入文件。

版本2:

使用CGContextRef(创建位图上下文)和等效的Quartz API可以实现同样的目的。这消除了对Objective C的需求,但结果代码会更长一些。您还可以使用Quartz(CGxxx)和AppKit(NSxxx)API的各种混合,但Quartz API通常使用起来比较麻烦(因为它们的灵活性,分配和其他问题)。

版本3:

您还可以使用Quartz + Core Text,即OS X 10.5+。这使您可以在确切的文本布局方面提供很大的灵活性,并且在将文本绘制到位图之前提供了一种相对简单的方法来测量文本的大小(因此您可以使位图足够大)。

脚注:在绘制文字之前,像歪斜之类的东西很容易应用。可以使用倾斜绘制文本(请参阅NSAffineTransformCocoa drawing guide)。

答案 2 :(得分:4)

我相信你想要的功能是CGContextShowTextAtPoint()

使用示例:

NSString *input = /* ... */;
CGContextRef context = /* create a graphics context */;

// make sure you have set up the font
CGContextShowTextAtPoint(context, 5, 5, [input UTF8String], [input length]);

答案 3 :(得分:2)

这是一个执行您所描述内容的最小命令行工具。将它传递给你想要保存结果的路径,例如:

" ./test foo.tiff"

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
      NSString *string = @"Hello, World!";
      NSString *path = [[[NSProcessInfo processInfo] arguments] objectAtIndex:1];

      NSDictionary *attributes =
        @{ NSFontAttributeName : [NSFont fontWithName:@"Helvetica" size:40.0],
        NSForegroundColorAttributeName : NSColor.blackColor};

      NSImage *image = [[NSImage alloc] initWithSize:[string sizeWithAttributes:attributes]];
      [image lockFocus];
      [string drawAtPoint:NSZeroPoint withAttributes:attributes];
      [image unlockFocus];
      [[image TIFFRepresentation] writeToFile:path atomically:YES];
    }
    return 0;
}