Does anyone have example code for vImage processing on iOS?
I have read through every bit of documentation out there that I can find, but cannot get a simple vImage call to work. I just need a real example. Documentation 开发者_StackOverflow中文版is very sparse.
If you're processing video in real-time, and your input is processed in a pixel buffer, here's how to copy that buffer into a vImage, at which point you can call whatever commands you like:
- (CVPixelBufferRef)copyRenderedPixelBuffer:(CVPixelBufferRef)pixelBuffer
{
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
// vImage processing
vImage_Error err;
vImage_Buffer buffer;
buffer.data = (unsigned char *)CVPixelBufferGetBaseAddress( pixelBuffer );
buffer.rowBytes = CVPixelBufferGetBytesPerRow( pixelBuffer );
buffer.width = CVPixelBufferGetWidth( pixelBuffer );
buffer.height = CVPixelBufferGetHeight( pixelBuffer );
vImageCVImageFormatRef vformat = vImageCVImageFormat_CreateWithCVPixelBuffer( pixelBuffer );
vImage_CGImageFormat cgformat = {
.bitsPerComponent = 8,
.bitsPerPixel = 32,
.bitmapInfo = kCGBitmapByteOrderDefault,
.colorSpace = NULL, //sRGB
};
const CGFloat bgColor[3] = {0.0, 0.0, 0.0};
vImageBuffer_InitWithCVPixelBuffer(&buffer, &cgformat, pixelBuffer, vformat, bgColor, kvImageNoAllocate);
vImage_Buffer outbuffer;
void *tempBuffer;
tempBuffer = malloc(CVPixelBufferGetBytesPerRow( pixelBuffer ) * CVPixelBufferGetHeight( pixelBuffer ));
outbuffer.data = tempBuffer;
outbuffer.rowBytes = CVPixelBufferGetBytesPerRow( pixelBuffer );
outbuffer.width = CVPixelBufferGetWidth( pixelBuffer );
outbuffer.height = CVPixelBufferGetHeight( pixelBuffer );
err = vImageEqualization_ARGB8888(&buffer, &outbuffer, kvImageNoFlags);
if(err != -1)
err = vImageContrastStretch_ARGB8888(&buffer, &outbuffer, kvImageNoFlags);
if(err != -1)
err = vImageBuffer_CopyToCVPixelBuffer(&outbuffer, &cgformat, pixelBuffer, vformat, bgColor, kvImageNoFlags);
if(err != -1)
free(tempBuffer);
CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
return (CVPixelBufferRef)CFRetain( pixelBuffer );
}
Updating Ole Bermann's answer: the Accelerate framework was added in iOS 5.0.
An even more advanced example, with optimization of the equalization and stretching functions (ignore commented out code, although you can use it—it works, too:
- (CVPixelBufferRef)copyRenderedPixelBuffer:(CVPixelBufferRef)pixelBuffer {
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
unsigned char *base = (unsigned char *)CVPixelBufferGetBaseAddress( pixelBuffer );
size_t width = CVPixelBufferGetWidth( pixelBuffer );
size_t height = CVPixelBufferGetHeight( pixelBuffer );
size_t stride = CVPixelBufferGetBytesPerRow( pixelBuffer );
vImage_Buffer _img = {
.data = base,
.height = height,
.width = width,
.rowBytes = stride
};
vImage_Error err;
vImage_Buffer _dstA, _dstR, _dstG, _dstB;
err = vImageBuffer_Init( &_dstA, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (alpha) error: %ld", err);
err = vImageBuffer_Init( &_dstR, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (red) error: %ld", err);
err = vImageBuffer_Init( &_dstG, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (green) error: %ld", err);
err = vImageBuffer_Init( &_dstB, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (blue) error: %ld", err);
err = vImageConvert_ARGB8888toPlanar8(&_img, &_dstA, &_dstR, &_dstG, &_dstB, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageConvert_ARGB8888toPlanar8 error: %ld", err);
err = vImageEqualization_Planar8(&_dstR, &_dstR, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (red) error: %ld", err);
err = vImageEqualization_Planar8(&_dstG, &_dstG, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (green) error: %ld", err);
err = vImageEqualization_Planar8(&_dstB, &_dstB, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (blue) error: %ld", err);
err = vImageConvert_Planar8toARGB8888(&_dstA, &_dstR, &_dstG, &_dstB, &_img, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageConvert_Planar8toARGB8888 error: %ld", err);
err = vImageContrastStretch_ARGB8888( &_img, &_img, kvImageNoError );
if (err != kvImageNoError)
NSLog(@"vImageContrastStretch_ARGB8888 error: %ld", err);
err = vImagePermuteChannels_ARGB8888(&_img, &_img, map, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImagePermuteChannels_ARGB8888 error: %ld", err);
free(_dstA.data);
free(_dstR.data);
free(_dstG.data);
free(_dstB.data);
CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
return (CVPixelBufferRef)CFRetain( pixelBuffer );
}
Documentation does not exist because the vImage libraries are not available on iOS.
vImage is available on iOS since 5.0. The documentation is here.
精彩评论