NSImage와 CGImage 변환하는 법

NSImage > CGImage로 변환하기

NSImagecgImage(forProposedRect:Context:hints:)라는 메소드를 가지고 있는데, 이는 어떤 영역에 그려질 최적의 CGImage 객체를 찾아서 리턴하는 기능을 수행한다.  이 때 모든 파라미터는 옵션이며, 전부 nil로 넣어도 상관없다. 다만 파라미터들은 NSImage가 가지고 있는 여러 개의 CGImage 표현형 중에서 어떤 것을 선택할지를 결정하는데 도움을 주는 힌트에 해당한다. 

proposedDestRect는 CG이미지를 사용할 영역에 대한 참조로 주로 어느 해상도(크기)에서 사용될 것인지를 정한다. 만약 nil을 전달하면 NSImage의 크기 영역을 기준으로 삼게 된다. context는 그래픽 컨텍스트이며, hints 값은 그외의 힌트가 된다. 

이미지 표현형을 통해서 얻기

사실 이 방법은 위의 메소드를 호출하는 것과 별반 다르지 않을텐데, NSImage가 이미지를 ‘다루는’데 목표를 둔 반면에 실제로 어떤 그림인지에 대해서는 신경쓰지 않는 특이한 구조에 착안하는 것이다. 표현되는 그림이 무엇인지는 representations 파라미터를 통해서 알 수 있는 것이다. 이는 [NSImageRep] 타입으로 실제 이미지를 나타내는 데이터들이 모여 있다. (그 중에는 비트맵도 있을 수 있고 벡터나 PDF 등 그 형식은 매우 다양할 수 있다.) 

하지만 해당 NSImage가 비트맵 이미지를 기반으로 생성되었다는 사실을 보장할 수 있다면, 해당 이미지의 표현형 중에서 NSBitmapImageRep 인 것을 고르고 그 중 하나 (대표적으로 가장 앞에 있는 것)의 cgImage 속성을 취하는 것이다. 

if let cgImage = (nsImage.representations as? [NSBitmapImageRep])?.first.cgImage {
  // use cgImage...
}

CGImage -> NSImage 로 변환하기

CGImageNSImageView등에서 표현하기 위해서는 다시 NSImage로 변환해야 한다. NSImage의 편의 이니셜라이저 중에는 init(cgImage:size:) 가 있는데 이것을 사용하면 된다. 

참고로 이 때 size 파라미터에 NSZeroSize를 사용하면, 주어진 CGImage의 픽셀 폭/높이를 기준으로 사이즈를 삼게된다. 

다른 한가지 방법으로는 앞에서 비트맵이미지 표현형(NSBitmapImageRep)을 사용한 방법을 거꾸로 한 것이 있다.  NSBitmapImageRepCGImage로 바로 생성이 가능하다. (또 CIImage로도!) 이렇게 만들어진 표현형을 빈 NSImage에 추가하는 것이다.

let rep = NSBitmapImageRep(cgImage: cgimage)
let image = NSImage()
image.addRepresentation(rep)