5

Cocoa でテキストを画像に変換する方法を探しています。テキストから画像への変換ではなく、画像からテキストへの変換を説明しているようです。

簡単に言えば、単語 (「Kevin」など) をビットマップ イメージに変換して操作し、JPEG として保存したいと考えています。

答えてくれた人はすごいです。3 つの異なる同じように有効な方法をありがとうございます (はい、私はそれらをテストしました)....非常にクールです。すべての正しい答えを教えていただければ幸いです。

4

4 に答える 4

8

編集:私は質問を読み間違え、あなたがCocoa-touchコードが欲しいと思いました(あなたがそうした場合に備えて、私はそれを最後に残しました)。CoreTextを使用してCocoaでそれを行う1つの方法を次に示します(別のポスターによると、さまざまな方法があります)。

{
    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関数であり、クラスの一部ではありません。

お役に立てれば!

于 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 が不要になりますが、その結果、コードが少し長くなります。CGxxxQuartz ( ) APIと AppKit ( ) APIをさまざまに組み合わせて使用​​することもできNSxxxますが、通常、Quartz API は (割り当てやその他の問題に関して柔軟性があるため) 使用するのがより面倒です。

バージョン 3:

OS X 10.5+ である Quartz + Core Text を使用することもできます。これにより、テキストを正確にどのようにレイアウトするかという点で多くの柔軟性が得られ、ビットマップに描画する前にテキストの大きさを比較的簡単に測定する方法も提供されます (ビットマップを十分に大きくすることができます)。

脚注:スキューなどは、テキストを描画する前に簡単に適用できます。テキストは傾斜して描画できます (NSAffineTransformおよびCocoa drawing guideを参照)。

于 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 に答える