2015-04-06 5 views
1

У меня есть два экземпляра NSImage. Я хочу, чтобы image2 располагался поверх изображения1 с определенным уровнем непрозрачности. Они имеют соответствующие размеры. Ни один из изображений не должен быть видимым в пользовательском интерфейсе.Смешайте два NSImages с помощью Swift на OS X

Как правильно настроить графический контекст и нарисовать на нем изображения, с полной непрозрачностью и еще одним полупрозрачным?

Здесь я читал несколько ответов, но я нахожу это сложным, тем более, что большинство из них, похоже, предназначены для Objective-C или применимы только к iOS. Любые указатели оцениваются. Если это может быть выполнено без необходимости использования CGContext, это будет еще лучше.

func blendImages(image1: NSImage, image2: NSImage, alpha: CGFloat) -> CGImage { 

    // Create context 
    var ctx: CGContextRef = CGBitmapContextCreate(0, inputImage.size.width, inputImage.size.height, 8, inputImage.size.width*4, NSColorSpace.genericRGBColorSpace(), PremultipliedLast) 
    let area = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height) 
    CGContextScaleCTM(ctx, 1, -1) 

    // Draw image1 in context 

    // Draw image2 with alpha opacity 
    CGContextSetAlpha(ctx, CGFloat(0.5)) 

    // Create CGImage from context 
    let outputImage = CGBitmapContextCreateImage(ctx) 

    return outputImage 
} 

В другом месте у меня есть это расширение, чтобы получить CGImages из моих NSImages:

extension NSImage { 
    var CGImage: CGImageRef { 
     get { 
      let imageData = self.TIFFRepresentation 
      let source = CGImageSourceCreateWithData(imageData as! CFDataRef, nil) 
      let maskRef = CGImageSourceCreateImageAtIndex(source, 0, nil) 
      return maskRef 
     } 
    } 
} 
+0

Это использование Swift 1.2 на OS X 10.10. – Henrik

ответ

3

мне удалось решить эту проблему с NSGraphicsContext.

func mergeImagesAB(pathA: String, pathB: String, fraction: CGFloat) -> CGImage { 

    guard let imgA = NSImage(byReferencingFile: pathA), 
     let imgB = NSImage(byReferencingFile: pathB), 
     let bitmap = imgA.representations[0] as? NSBitmapImageRep, 
     let ctx = NSGraphicsContext(bitmapImageRep: bitmap) 
     else {fatalError("Failed to load images.")} 

    let rect = NSRect(origin: CGPoint(x: 0, y: 0), size: bitmap.size) 

    NSGraphicsContext.saveGraphicsState() 
    NSGraphicsContext.setCurrentContext(ctx) 
    imgB.drawInRect(rect, fromRect: rect, operation: .CompositeSourceOver, fraction: fraction) 
    NSGraphicsContext.restoreGraphicsState() 

    guard let result = bitmap.CGImage 
     else {fatalError("Failed to create image.")} 

    return result; 
} 
+0

Позже я обнаружил, что полоса пропускания связана с настройками по умолчанию для сохранения изображений JPEG. Используя более высокое качество, бандажи в основном уходили. Таким образом, 64-битный контекст, вероятно, не нужен в большинстве случаев. – Henrik

0

Спасибо Henrik, мне это было нужно для Obj-C. Вот эта версия на тот случай, если кому-то также нужны:

-(CGImageRef) mergeImage:(NSImage*)a andB:(NSImage*)b fraction:(float)fraction{ 
    NSBitmapImageRep *bitmap = (NSBitmapImageRep*)[[a representations] objectAtIndex:0]; 
    NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap]; 
    [NSGraphicsContext saveGraphicsState]; 
    [NSGraphicsContext setCurrentContext:ctx]; 

    CGRect rect = CGRectMake(0, 0, bitmap.size.width, bitmap.size.height); 
    [NSGraphicsContext saveGraphicsState]; 
    [NSGraphicsContext setCurrentContext:ctx]; 
    [b drawInRect:rect fromRect:rect operation:NSCompositeSourceOver fraction:fraction]; 
    [NSGraphicsContext restoreGraphicsState]; 

    return [bitmap CGImage]; 
}