最近在公司寫有關影音的app常常遇到需要把webcam的image轉成小圖,samplebuffer轉cgimage的方法網路一堆,不過還是記錄一下做法,共五個步驟
- 先用function CMSampleBufferGetImageBuffer來得到CVImageBufferRef
- CVPixelBufferGet*之類的function來獲得buffer的資訊(影像的長寬還有image所在的記憶體位置)
- create color space
- 然後用CGBitmapContextCreate將image畫在context上
- 最後用CGBitmapContextCreateImage這個function產生CGImage
// 1. Get Image Buffer
CVImageBufferRef imageBuffer= CMSampleBufferGetImageBuffer(sampleBuffer);
// Lock Image to avoid sync problem
CVPixelBufferLockBaseAddress(imageBuffer,0);
// 2. Get imageBuffer information
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
// 3. Create color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// 4. Draw sampleBuffer on context
CGContextRef context = CGBitmapContextCreate(baseAddress,
width,
height,
8,
bytesPerRow,
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
if(!context){
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
return;
}
CGColorSpaceRelease(colorSpace);
// 5. Create CGImage from context
cgImage = CGBitmapContextCreateImage(context);
上面的code google一下應該就有很多類似的code(話說去年要找到類似的code還真給他困難),當然現在要面對的是怎麼Resize image,UIImage或是NSImage都可以轉換成CGImage,所以這裡只記錄從CGImage怎麼Resize,主要有有四個步驟
- 用malloc create一塊記憶體空間放context
- 將步驟一的記憶體空間給context
- 將原來的CGImage畫到context上面
- 用CGBitmapContextCreateImage這function create CGImage
// Assume we already have a CGImage: originCGImage
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
size_t resizeWidth = 640;
size_t resizeHeight = height*640/width;
// 1. Create a memory to store Image
uint32_t *pixels = (uint32_t *)malloc(resizeWidth*resizeHeight*sizeof(uint32_t));
// 2. Create an empty context
CGContextRef context = CGBitmapContextCreate(pixels,
resizeWidth,
resizeHeight,
8,
resizeWidth*sizeof(uint32_t),
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
// 3. Draw Image to context
CGContextDrawImage(context, CGRectMake(0, 0, resizeWidth, resizeHeight), originCGImage);
// 4. Create a new CGImage
CGImageRef newCGImage = CGBitmapContextCreateImage(context);
free(pixels);
CGImageRelease(originCGImage);
CGColorSpaceRelease(colorSpace);
基本resize的想法很簡單,假設已經有一個想要resize的CGImage,要做的事情就是1. 開記憶體->2. 把記憶體配給一張畫布(context)-> 3. 用CGContextDrawImage這個function把原本的CGImage畫到畫布上->4. 根據這個畫布來create新的CGImage,當然最後還要記得把該free掉或release掉的都清掉,不然會造成memory leak,這是在操作CG框架庫要注意的!原因就跟CG是C language所寫出來的有關,ARC memory manage在這個部分並沒有支援,所以拉!如果以前寫C有free的好習慣,使用CG framework的時候也記得要保持好習慣,不要被ARC這厲害的東西給寵壞惹!
沒有留言:
張貼留言