5

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

简单地说,我想取一个词(比如“Kevin”),将其转换为位图图像来操作并保存为JPEG。

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

4

4 回答 4

8

编辑:我误读了这个问题,并假设你想要 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 编程时,我发现以下事情不直观或不寻常。测量和绘制字符串的方法是 on NSString(不是其他系统中的图形上下文)的方法。保存数据的方法NSData不是文件类的方法!创建图形上下文的函数是纯 C 函数,不属于任何类。

希望这可以帮助!

于 2012-07-12T01:13:27.253 回答
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 通常使用起来更麻烦(因为它们的灵活性 wrt. 分配和其他问题)。

版本 3:

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

脚注:在绘制文本之前,像倾斜这样的东西很容易应用。文本可以倾斜绘制(参见NSAffineTransformCocoa绘图指南)。

于 2012-07-12T01:43:50.540 回答
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]);
于 2012-07-11T23:31:27.190 回答
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;
}
于 2012-07-12T04:22:00.587 回答