最近在公司寫有關影音的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這厲害的東西給寵壞惹!
沒有留言:
張貼留言