使用Cocoa / OSX合并/堆叠两个图像

时间:2013-09-03 03:03:16

标签: objective-c macos cocoa

我有一个CGImageRef(让我们称之为原始图像)和一个透明的png(水印)。我正在尝试编写一种方法将水印放在原始顶部,并返回CGImageRef。

在iOS中,我会使用UIKit将它们都绘制到上下文中,但这似乎不适用于OSX(不支持UIKit)。

什么是堆叠两张图片的最简单方法?感谢

3 个答案:

答案 0 :(得分:12)

对于快速的肮脏解决方案,您可以使用NSImage绘图API:

NSImage *background = [NSImage imageNamed:@"background"];
NSImage *overlay = [NSImage imageNamed:@"overlay"];

NSImage *newImage = [[NSImage alloc] initWithSize:[background size]];
[newImage lockFocus];

CGRect newImageRect = CGRectZero;
newImageRect.size = [newImage size];

[background drawInRect:newImageRect];
[overlay drawInRect:newImageRect];

[newImage unlockFocus];

CGImageRef newImageRef = [newImage CGImageForProposedRect:NULL context:nil hints:nil];

如果您不喜欢这样,那么您期望的大多数CGContext API都可以跨平台进行绘制,并且可以进行更多控制。同样,您可以查看NSGraphicsContext。

答案 1 :(得分:5)

渲染到CGContext时,这非常简单。

如果您想要一个图像作为结果,您可以创建并渲染到CGBitmapContext,然后在渲染后请求图像。

一般流程,省略了常见细节和上下文信息:

CGImageRef CreateCompositeOfImages(CGImageRef pBackground,
                                   const CGRect pBackgroundRect,
                                   CGImageRef pForeground,
                                   const CGRect pForegroundRect)
{
  // configure context parameters
  CGContextRef gtx = CGBitmapContextCreate( %%% );

  // configure context

  // configure context to render background image
  // draw background image
  CGContextDrawImage(gtx, pBackgroundRect, pBackground);

  // configure context to render foreground image
  // draw foreground image
  CGContextDrawImage(gtx, pForegroundRect, pForeground);

  // create result
  CGImageRef result = CGBitmapContextCreateImage(gtx);

  // cleanup

  return result;
}

您需要从PNG创建CGImage。

您可能有兴趣使用的其他API:

  • CGContextSetBlendMode
  • CGContextSetAllowsAntialiasing
  • CGContextSetInterpolationQuality

我知道很多人通常建议您使用更高级别的抽象(即AppKit和UIKit),但CoreGraphics是一个很棒的库,可以在这两种情境中进行渲染。如果您对在OS X和iOS中都易于使用的图形实现感兴趣,那么如果您愿意使用这些抽象,CoreGraphics是您工作的一个很好的选择。

答案 2 :(得分:1)

如果像我这样的人需要Swift版本。

这是功能齐全的Swift 5版本:

let background = NSImage(named: "background")
let overlay = NSImage(named: "overlay")

let newImage = NSImage(size: background.size)
newImage.lockFocus()

var newImageRect: CGRect = .zero
newImageRect.size = newImage.size

background.draw(in: newImageRect)
overlay.draw(in: newImageRect)

newImage.unlockFocus()

我希望我有时间对CGContext示例进行同样的操作。