2012-08-31 19 views
12

He estado programando durante dos años en iOS y nunca en Mac. Estoy trabajando en una pequeña utilidad para manejar algunas necesidades de imagen simples que tengo en mi desarrollo de iOS. De todos modos, tengo un código de trabajo en iOS que funciona perfectamente pero no tengo ni idea de qué equivalentes son para mac.iOS a Mac GraphicContext Explicación/Conversión

He intentado un montón de cosas diferentes, pero realmente no entiendo cómo iniciar un contexto de gráficos en la Mac fuera de un método "drawRect:". En el iPhone, simplemente usaría UIGraphicsBeghinImageContext(). Sé que otras publicaciones me han dicho que utilicen lockFocus/unlockFocus, pero no estoy seguro de cómo hacerlo exactamente para mis necesidades. Ah, y realmente echo de menos la propiedad "CGImage" de UIImage. No entiendo por qué NSImage no puede tener uno, aunque suena un poco más complicado que eso.

Aquí está mi código de trabajo en IOS-básicamente sólo crea una imagen reflejada de una máscara y los combina juntos:

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 

Cualquier sugerencia para lograr esto (sólo) en el Mac?

+1

simple: '(CGContextRef) [[NSGraphicsContext CurrentContext] graphicsPort]' – CodaFi

+0

¿Eso se inicia un contexto gráfico? Si es así, ¿cómo puedo dibujar las imágenes y recuperarlas (como UIGraphicsGetImageFromCurrentImageContext()). Además, ¿cómo voy a ir entre un NSImage y CGImage? – daveMac

+1

Se agregó una versión de Swift: http://stackoverflow.com/a/34361216/1226095 –

Respuesta

19

Aquí está un ejemplo sencillo que dibuja un círculo azul en un NSImage (estoy usando ARC en este ejemplo, añadir conserva/comunicados al gusto)

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]; 

La diferencia principal es que en OS X por primera vez tiene que crear la imagen, entonces puede comenzar a dibujar en ella; en iOS, usted crea el contexto y luego extrae la imagen de él.

Básicamente, lockFocus hace que el contexto actual sea la imagen y se dibuja directamente en él, luego utiliza la imagen.

No estoy del todo seguro de si esto responde a todas sus preguntas, pero creo que es al menos una parte.

+0

Así que pensé que eso era lo que bloquea el enfoque, pero ¿cómo podría hacer algo como voltear la imagen? He intentado voltear el contexto y luego dibujar la imagen en él, pero la imagen siempre sale con el lado derecho hacia arriba. Otra cosa, ¿TIFF es el único formato en el que puedo guardar? – daveMac

+0

Se agregó una versión de Swift: http://stackoverflow.com/a/34361216/1226095 –

9

Bueno, aquí está la nota en UIGraphicsBeginImageContextWithOptions:

UIGraphicsBeginImageContextWithOptions

Crea un contexto gráfico basado en mapa de bits con las opciones especificadas.

El equivalente OS X, que también está disponible en iOS (y UIGraphicsBeginImageContextWithOptions es posiblemente una envoltura alrededor) es CGBitmapContextCreate:

declararse como:

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

Aunque es un C API, podrías pensar en CGBitmapContext como una subclase de CGContext. Se procesa en un búfer de píxeles, mientras que un CGContext se representa en un destino abstracto.

Para UIGraphicsGetImageFromCurrentImageContext, puede usar CGBitmapContextCreateImage y pasar su contexto de mapa de bits para crear una imagen CG.

7

Aquí hay un Swift (2.1/10.11 API-compatible) versión de 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

versión Swift3 de 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()