본문 바로가기

프로그래밍/iOS,macOS

Image, PixelBuffer

CMSampleBuffer -> CVPixelBuffer

let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

 

CVPixelBuffer -> CIImage

let ciimage = CIImage(cvPixelBuffer: pixelBuffer)

 

CIImage -> CGImage

context 생성은 비용이 높으므로, 미리 생성해 두고 사용

let context = CIContext(options: nil)
let cgImage = context.createCGImage(ciimage, from: ciimage.extent)!

 

CIImage, CGImage -> UIImage

let uiImage = UIImage(CIImage: ciImage)
let uiImage = UIImage(CGImage: cgImage)

 

UIImage, CGImage -> CIImage

var ciImage = CIImage(image: uiImage)
var ciImage = CIImage(CGImage: cgImage)

 

CIImage - > CVPixelBuffer

let context = CIContext()
context.render(ciImage, to: pixelBuffer)

 

UIImage -> CVPixelBuffer


var pixelBuffer: CVPixelBuffer? = nil
let attributes = [
    String(kCVPixelBufferCGImageCompatibilityKey): false,
    String(kCVPixelBufferCGBitmapContextCompatibilityKey): false,
] as CFDictionary

// 사이즈 정보
let width = Int(uiImage.size.width)
let height = Int(uiImage.size.height)
let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB()

// bgra : .bytePrder32Littel
// argb : .noneSkipFirst
// gray : .none
let alphInfo: CGImageAlphaInfo = .byteOrder32Little
let pixelFormat: OSType = kCVPixelFormatType_32BGRA

// 픽셀버퍼 생성
let result = CVPixelBufferCreate( kCFAllocatorDefault,
                                  width,
                                  height,
                                  pixelFormat,
                                  attributes, 
                                  &pixelBuffer)

guard let pixelBuffer = pixelBuffer else { return nil }
let flag = CVPixelBufferLockFlags(rawValue: 0)

CVPixelBufferLockBaseAddress(pixelBuffer, flag)
defer {
   CVPixelBufferUnlockBaseAddress(pixelBuffer, flag)
}

let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)

let context = CGContext(data: pixelData,
                        width: width,
                        height: height,
                        bitsPerComponent: 8,
                        bytesPerRow: bytesPerRow,
                        space: colorSpace,
                        bitmapInfo: alphaInfo.rawValue )

// bitmap 형식 기준 좌표 변경
context?.translateBy(x: 0, y: CGFlaot(height))
context?.scaleBy(x: 1, y: -1)

// 이미지 그리기
context?.draw(uiImage.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: width, height: height))

 

CVPixelBuffer -> CMSampleBuffer


let pixelBuffer = cvPixelBuffer
var sampleBuffer: CMSampleBuffer? = nil

// 타임 정보
var timimgInfo: CMSampleTimingInfo = CMSampleTimingInfo.invalid
var videoInfo: CMVideoFormatDescription? = nil


CMVideoFormatDescriptionCreateForImageBuffer(allocator: nil, 
                                  imageBuffer: pixelBuffer!, 
                                  formatDescriptionOut: &videoInfo)

CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault, 
                                   imageBuffer: pixelBuffer!, 
                                   dataReady: true, 
                                   makeDataReadyCallback: nil, 
                                   refcon: nil, 
                                   formatDescription: videoInfo!, 
                                   sampleTiming: &timimgInfo, 
                                   sampleBufferOut: &sampleBuffer)

 

 

CGImage - > Array

var array = [UInt8](repeating: 0, count: cgImage.width * cgImage.height * 4)
array.withUnsafeMutableBytes { ptr in
    let context = CGContext( data: ptr.baseAddress,
                             width: cgImage.width,
                             height: cgImage.height
                             bitsPerComponent: cgImage.bitsPerComponent,
                             bytesPerRow: cgImage.bytesPerRow,
                             space: cgImage.colorSpace,
                             bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
     let rect = CGRect( origin: .zero, size: CSize(width: cgImage.width, height: cgImage.height))
     context?.draw(cgImage, in: rect)

}

 

Array -> CGImage

배열의 경우 width, height, bitsPerComponent, bytesPerRow, colorSpace 등 이미지에 대한
기본 정보를 별도 관리 해야함.

var cgImage = array.withUnsafeBytes { ptr in
   var data = UnsafeMutableRawPointer(mutating: ptr.baseAddress)
   
   let context = CGContext(data: data,
                           width: width,
                           height: height,
                           bitsPerComponent: 8,
                           bytesPerRow: bytesPerRow,
                           space: colorSpace,
                           bitmapInfo, alphaInfo.rawValue)
    return context?.makeImage()
}