2012-08-31 23 views
12

我在iOS上編程了兩年,從未在Mac上編程過。我正在處理一些用於處理iOS開發中的一些簡單圖像需求的實用程序。無論如何,我有工作代碼在iOS中運行完美,但我絕對不知道什麼是等效的Mac。iOS to Mac GraphicContext說明/轉換

我試過了一堆不同的東西,但我真的不明白如何在Mac上在「drawRect:」方法之外啓動圖形上下文。在iPhone上,我只會使用UIGraphicsBeghinImageContext()。我知道其他職位已經說過要使用lockFocus/unlockFocus,但我不知道如何完全按照我的需求做這件事。哦,我真的很想念UIImage的「CGImage」屬性。我不明白爲什麼NSImage不能有一個,雖然聽起來有點棘手。

下面是iOS上,基本上我的工作代碼,它只是從面具創建一個反射的圖像,並將它們融合在一起:

UIImage *mask = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"Mask_Image.jpg" ofType:nil]]; 
    UIImage *image = [UIImage imageNamed::@"Test_Image1.jpg"]; 
    UIGraphicsBeginImageContextWithOptions(mask.size, NO, [[UIScreen mainScreen]scale]); 
    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    CGContextTranslateCTM(ctx, 0.0, mask.size.height); 
    CGContextScaleCTM(ctx, 1.f, -1.f); 
    [image drawInRect:CGRectMake(0.f, -mask.size.height, image.size.width, image.size.height)]; 
    UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    CGImageRef maskRef = mask.CGImage; 
    CGImageRef maskCreate = CGImageMaskCreate(CGImageGetWidth(maskRef), 
               CGImageGetHeight(maskRef), 
               CGImageGetBitsPerComponent(maskRef), 
               CGImageGetBitsPerPixel(maskRef), 
               CGImageGetBytesPerRow(maskRef), 
               CGImageGetDataProvider(maskRef), NULL, false); 
    CGImageRef masked = CGImageCreateWithMask([flippedImage CGImage], maskCreate); 

    CGImageRelease(maskCreate); 

    UIImage *maskedImage = [UIImage imageWithCGImage:masked]; 
    CGImageRelease(masked); 

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height + (image.size.height * .5)), NO, [[UIScreen mainScreen]scale]); 

    [image drawInRect:CGRectMake(0,0, image.size.width, image.size.height)]; 
    [maskedImage drawInRect:CGRectMake(0, image.size.height, maskedImage.size.width, maskedImage.size.height)]; 

    UIImage *anotherImage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

//do something with anotherImage 

任何建議在Mac平臺上實現這種(簡單)?

+1

簡單Swift3版本:'(CGContextRef)[[獲取到NSGraphicsContext currentContext] graphicsPort]' – CodaFi

+0

這是否啓動圖形上下文?如果是這樣,那我該如何繪製圖像並檢索它們(如UIGraphicsGetImageFromCurrentImageContext())。另外,我將如何去NSImage和CGImage之間? – daveMac

+1

增加了一個Swift版本:http://stackoverflow.com/a/34361216/1226095 –

回答

19

這裏有一個簡單的例子,繪製一個藍色圓圈爲NSImage中(我在這個例子中使用ARC,添加保留/釋放適量)

NSSize size = NSMakeSize(50, 50); 

NSImage* im = [[NSImage alloc] initWithSize:size]; 
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] 
          initWithBitmapDataPlanes:NULL 
              pixelsWide:size.width 
              pixelsHigh:size.height 
             bitsPerSample:8 
            samplesPerPixel:4 
              hasAlpha:YES 
              isPlanar:NO 
             colorSpaceName:NSCalibratedRGBColorSpace 
             bytesPerRow:0 
             bitsPerPixel:0]; 

[im addRepresentation:rep]; 

[im lockFocus]; 

CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; 
CGContextClearRect(ctx, NSMakeRect(0, 0, size.width, size.height)); 
CGContextSetFillColorWithColor(ctx, [[NSColor blueColor] CGColor]); 
CGContextFillEllipseInRect(ctx, NSMakeRect(0, 0, size.width, size.height)); 

[im unlockFocus]; 

[[im TIFFRepresentation] writeToFile:@"/Users/USERNAME/Desktop/foo.tiff" atomically:NO]; 

的主要區別是,在OS X中,第一必須創建圖像,然後才能開始繪製圖像;在iOS上創建上下文,然後從中提取圖像。

基本上,lockFocus使當前上下文成爲圖像,並直接繪製到它上面,然後使用圖像。

我不完全確定這是否回答您的所有問題,但我認爲這至少是其中的一部分。

+0

所以我覺得這是鎖定焦點,但我會怎麼做像翻轉圖像?我試圖翻轉上下文,然後在其中繪製圖像,但圖像始終正面朝上。另一件事,TIFF是我可以節省的唯一格式嗎? – daveMac

+0

添加了Swift版本:http://stackoverflow.com/a/34361216/1226095 –

9

好了,這裏的一對UIGraphicsBeginImageContextWithOptions注:

UIGraphicsBeginImageContextWithOptions

創建具有指定選項的基於位圖的圖形上下文。

的OS X當量,這也是在IOS可用的(和UIGraphicsBeginImageContextWithOptions可能是圍繞一個包裝)是CGBitmapContextCreate

聲明爲:

CGContextRef CGBitmapContextCreate (
    void *data, 
    size_t width, 
    size_t height, 
    size_t bitsPerComponent, 
    size_t bytesPerRow, 
    CGColorSpaceRef colorspace, 
    CGBitmapInfo bitmapInfo 
); 

雖然這是一個C API,您可以將CGBitmapContext視爲CGContext的子類。它呈現給像素緩衝區,而CGContext呈現給抽象目的地。

對於UIGraphicsGetImageFromCurrentImageContext,您可以使用CGBitmapContextCreateImage並傳遞位圖上下文來創建CGImage。

7

這是一個Swift(2.1/10。兼容的API 11)版Cobbal's answer

let size = NSMakeSize(50, 50); 
    let im = NSImage.init(size: size) 

    let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil, 
     pixelsWide: Int(size.width), 
     pixelsHigh: Int(size.height), 
     bitsPerSample: 8, 
     samplesPerPixel: 4, 
     hasAlpha: true, 
     isPlanar: false, 
     colorSpaceName: NSCalibratedRGBColorSpace, 
     bytesPerRow: 0, 
     bitsPerPixel: 0) 

    im.addRepresentation(rep!) 
    im.lockFocus() 

    let rect = NSMakeRect(0, 0, size.width, size.height) 
    let ctx = NSGraphicsContext.currentContext()?.CGContext 
    CGContextClearRect(ctx, rect) 
    CGContextSetFillColorWithColor(ctx, NSColor.blackColor().CGColor) 
    CGContextFillRect(ctx, rect) 

    im.unlockFocus() 
0

Cobbal's answer

let size = NSMakeSize(50, 50); 
    let im = NSImage.init(size: size) 

    let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil, 
            pixelsWide: Int(size.width), 
            pixelsHigh: Int(size.height), 
            bitsPerSample: 8, 
            samplesPerPixel: 4, 
            hasAlpha: true, 
            isPlanar: false, 
            colorSpaceName: NSCalibratedRGBColorSpace, 
            bytesPerRow: 0, 
            bitsPerPixel: 0) 


    im.addRepresentation(rep!) 
    im.lockFocus() 

    let rect = NSMakeRect(0, 0, size.width, size.height) 
    let ctx = NSGraphicsContext.current()?.cgContext 
    ctx!.clear(rect) 
    ctx!.setFillColor(NSColor.black.cgColor) 
    ctx!.fill(rect) 

    im.unlockFocus()